예제 #1
0
        protected internal override bool Walk(TryStatement node)
        {
            ExceptionBlock block = new ExceptionBlock(node);

            _tryBlocks.Push(block);
            WalkNode(node.Body);

            IList<CatchBlock> handlers = node.Handlers;
            if (handlers != null) {
                block.State = ExceptionBlock.TryStatementState.Handler;
                for (int handler = 0; handler < handlers.Count; handler++) {
                    block.Handler = handler;
                    WalkNode(handlers[handler].Body);
                }
            }

            if (node.FinallyStatement != null) {
                block.State = ExceptionBlock.TryStatementState.Finally;
                WalkNode(node.FinallyStatement);
            }

            Debug.Assert((object)block == (object)_tryBlocks.Peek());
            _tryBlocks.Pop();

            return false;
        }
예제 #2
0
		public Label BeginExceptionBlock()
		{
			ExceptionBlock block = new ExceptionBlock(exceptions.Count);
			block.labelEnd = DefineLabel();
			block.tryOffset = code.Position;
			exceptionStack.Push(block);
			exceptions.Add(block);
			stackHeight = 0;
			return block.labelEnd;
		}
예제 #3
0
        ExceptionBlock GetTryBlock()
        {
            ExceptionBlock tryBlk = GetBlock() as ExceptionBlock;

            if (tryBlk == null)
            {
                throw new InvalidOperationException("Statement can be used only in an exception block");
            }
            return(tryBlk);
        }
예제 #4
0
        ExceptionBlock GetTryBlock()
        {
            ExceptionBlock tryBlk = GetBlock() as ExceptionBlock;

            if (tryBlk == null)
            {
                throw new InvalidOperationException(Messages.ErrInvalidExceptionStatement);
            }
            return(tryBlk);
        }
예제 #5
0
        public void BeginCatchBlock(Type exceptionType)
        {
            ExceptionBlock block = exceptionStack.Peek();

            if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
            {
                if (exceptionType == null)
                {
                    Emit(OpCodes.Endfilter);
                }
                else
                {
                    Emit(OpCodes.Leave, block.labelEnd);
                }
            }
            stackHeight = 0;
            UpdateStack(1);
            if (exceptionType == null)
            {
                if (block.exceptionType != MarkerType.Filter || block.handlerOffset != 0)
                {
                    throw new ArgumentNullException("exceptionType");
                }
                block.handlerOffset = code.Position;
            }
            else
            {
                if (block.tryLength == 0)
                {
                    block.tryLength = code.Position - block.tryOffset;
                }
                else
                {
                    block.handlerLength = code.Position - block.handlerOffset;
                    exceptionStack.Pop();
                    ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count);
                    newBlock.labelEnd  = block.labelEnd;
                    newBlock.tryOffset = block.tryOffset;
                    newBlock.tryLength = block.tryLength;
                    block = newBlock;
                    exceptions.Add(block);
                    exceptionStack.Push(block);
                }
                block.exceptionType = exceptionType;
                if (exceptionType == MarkerType.Filter)
                {
                    block.filterOffset = code.Position;
                }
                else
                {
                    block.handlerOffset = code.Position;
                }
            }
        }
예제 #6
0
        public override bool Walk(TryFinallyStmt node)
        {
            TryFinallyBlock tfb = new TryFinallyBlock(node);

            tryBlocks.Push(tfb);
            node.body.Walk(this);
            tfb.state = ExceptionBlock.State.Finally;
            node.finallyStmt.Walk(this);
            ExceptionBlock eb = tryBlocks.Pop();

            Debug.Assert((object)eb == (object)tfb);
            return(false);
        }
예제 #7
0
        ExceptionBlock GetAnyTryBlock()
        {
            foreach (Block blk in blocks)
            {
                ExceptionBlock tryBlk = blk as ExceptionBlock;

                if (tryBlk != null)
                {
                    return(tryBlk);
                }
            }

            return(null);
        }
예제 #8
0
		public void EndExceptionBlock()
		{
			ExceptionBlock block = exceptionStack.Pop();
			if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
			{
				if (block.filterOffset != 0 || (block.exceptionType != MarkerType.Finally && block.exceptionType != MarkerType.Fault))
				{
					Emit(OpCodes.Leave, block.labelEnd);
				}
				else
				{
					Emit(OpCodes.Endfinally);
				}
			}
			MarkLabel(block.labelEnd);
			block.handlerLength = code.Position - block.handlerOffset;
		}
예제 #9
0
        public override void PostWalk(YieldStmt node)
        {
            topYields[node.index] = new YieldTarget(cg.DefineLabel());

            if (tryBlocks.Count == 0)
            {
                node.label = topYields[node.index].topBranchTarget;
            }
            else if (tryBlocks.Count == 1)
            {
                ExceptionBlock eb = tryBlocks.Peek();
                eb.AddYieldTarget(node, topYields[node.index], cg);
            }
            else
            {
                throw new NotImplementedException("yield in more than one try block");
            }
        }
예제 #10
0
        public void EndExceptionBlock()
        {
            ExceptionBlock block = exceptionStack.Pop();

            if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
            {
                if (block.kind != ExceptionHandlingClauseOptions.Finally && block.kind != ExceptionHandlingClauseOptions.Fault)
                {
                    Emit(OpCodes.Leave, block.labelEnd);
                }
                else
                {
                    Emit(OpCodes.Endfinally);
                }
            }
            MarkLabel(block.labelEnd);
            block.handlerLength = code.Position - block.handlerOffset;
        }
예제 #11
0
        public void EndHandler(ExceptionBlock block, LabelledExceptionHandler handler)
        {
            switch (handler.handlerType)
            {
            case ExceptionHandlerType.Filter:
                Emit(OpCodes.Endfilter);
                break;

            case ExceptionHandlerType.Finally:
                Emit(OpCodes.Endfinally);
                break;

            default:
                Emit(OpCodes.Leave, block.skip);
                break;
            }

            MarkLabel(block.skip);
            pendingExceptionHandlers.Add(block.cur);
        }
예제 #12
0
        public void EndExceptionBlock()
        {
            ExceptionBlock block = exceptionStack.Pop();

            if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
            {
                if (block.filterOffset != 0 || (block.exceptionType != null && block.exceptionType != FAULT))
                {
                    Emit(OpCodes.Leave, block.labelEnd);
                }
                else
                {
                    Emit(OpCodes.Endfinally);
                }
                if (IsLabelReachable(block.labelEnd))
                {
                    MarkLabel(block.labelEnd);
                }
            }
            block.handlerLength = code.Position - block.handlerOffset;
        }
예제 #13
0
        private void BeginFinallyFaultBlock(Type type)
        {
            ExceptionBlock block = exceptionStack.Peek();

            if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
            {
                Emit(OpCodes.Leave, block.labelEnd);
            }
            if (block.handlerOffset == 0)
            {
                block.tryLength = code.Position - block.tryOffset;
            }
            else
            {
                block.handlerLength = code.Position - block.handlerOffset;
                Label labelEnd;
                if (exceptionBlockAssistanceMode != EBAM_COMPAT)
                {
                    labelEnd = block.labelEnd;
                }
                else
                {
                    MarkLabel(block.labelEnd);
                    labelEnd = DefineLabel();
                    Emit(OpCodes.Leave, labelEnd);
                }
                exceptionStack.Pop();
                ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count);
                newBlock.labelEnd  = labelEnd;
                newBlock.tryOffset = block.tryOffset;
                newBlock.tryLength = code.Position - block.tryOffset;
                block = newBlock;
                exceptions.Add(block);
                exceptionStack.Push(block);
            }
            block.handlerOffset = code.Position;
            block.exceptionType = type;
            stackHeight         = 0;
        }
예제 #14
0
        private ExceptionBlock BeginFinallyFilterFaultBlock()
        {
            ExceptionBlock block = exceptionStack.Peek();

            if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
            {
                Emit(OpCodes.Leave, block.labelEnd);
            }
            stackHeight = 0;
            if (block.handlerOffset == 0)
            {
                block.tryLength = code.Position - block.tryOffset;
            }
            else
            {
                block.handlerLength = code.Position - block.handlerOffset;
                bool  reachable = IsLabelReachable(block.labelEnd);
                Label labelEnd  = new Label();
                if (reachable)
                {
                    MarkLabel(block.labelEnd);
                }
                labelEnd = DefineLabel();
                if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && reachable))
                {
                    Emit(OpCodes.Leave, labelEnd);
                }
                exceptionStack.Pop();
                ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count);
                newBlock.labelEnd  = labelEnd;
                newBlock.tryOffset = block.tryOffset;
                newBlock.tryLength = code.Position - block.tryOffset;
                block = newBlock;
                exceptions.Add(block);
                exceptionStack.Push(block);
            }
            return(block);
        }
예제 #15
0
        public override bool Walk(TryStmt node)
        {
            TryBlock tb = new TryBlock(node);

            tryBlocks.Push(tb);
            node.body.Walk(this);

            tb.state = TryBlock.State.Handler;
            foreach (TryStmtHandler handler in node.handlers)
            {
                handler.Walk(this);
            }

            ExceptionBlock eb = tryBlocks.Pop();

            Debug.Assert((object)tb == (object)eb);

            if (node.elseStmt != null)
            {
                node.elseStmt.Walk(this);
            }
            return(false);
        }
예제 #16
0
        public void BeginFinallyBlock()
        {
            ExceptionBlock block = BeginFinallyFilterFaultBlock();

            block.handlerOffset = code.Position;
        }
예제 #17
0
        /// <summary>
        ///     Write method body to a ILDasm -like representation
        /// </summary>
        /// <param name="mb">Method body to write</param>
        /// <returns>String representation of the method body (locals and instruction)</returns>
        /// <exception cref="ArgumentOutOfRangeException">Unexpected exception block type</exception>
        public static string ToILDasmString(this MethodBody mb)
        {
            var sb = new StringBuilder();

            var instrs = mb.Instructions;

            // Fixup the the offsets
            var prev = instrs.First();

            prev.Offset = 0;
            foreach (var ins in instrs.Skip(1))
            {
                var operand = prev.Operand;

                if (operand is ILLabel label)
                {
                    prev.Operand = label.Target;
                }
                else if (operand is ILLabel[] labels)
                {
                    prev.Operand = labels.Select(l => l.Target).ToArray();
                }

                ins.Offset = prev.Offset + prev.GetSize();

                prev.Operand = operand;

                prev = ins;
            }

            // Cache exception blocks for pretty printing
            var exBlocks = new Dictionary <Instruction, List <ExceptionBlock> >();

            ExceptionBlock AddBlock(Instruction ins, ExceptionBlockType t)
            {
                if (ins == null)
                {
                    return(new ExceptionBlock(0));
                }
                if (!exBlocks.TryGetValue(ins, out var list))
                {
                    exBlocks[ins] = list = new List <ExceptionBlock>();
                }
                var block = new ExceptionBlock(t);

                list.Add(block);
                return(block);
            }

            foreach (var exHandler in mb.ExceptionHandlers)
            {
                AddBlock(exHandler.TryStart, ExceptionBlockType.BeginExceptionBlock);
                AddBlock(exHandler.TryEnd, ExceptionBlockType.EndExceptionBlock);
                AddBlock(exHandler.HandlerEnd, ExceptionBlockType.EndExceptionBlock);
                switch (exHandler.HandlerType)
                {
                case ExceptionHandlerType.Catch:
                    AddBlock(exHandler.HandlerStart, ExceptionBlockType.BeginCatchBlock).catchType =
                        exHandler.CatchType.ResolveReflection();
                    break;

                case ExceptionHandlerType.Filter:
                    AddBlock(exHandler.FilterStart, ExceptionBlockType.BeginExceptFilterBlock);
                    break;

                case ExceptionHandlerType.Finally:
                    AddBlock(exHandler.HandlerStart, ExceptionBlockType.BeginFinallyBlock);
                    break;

                case ExceptionHandlerType.Fault:
                    AddBlock(exHandler.HandlerStart, ExceptionBlockType.BeginFaultBlock);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            var       indent       = 0;
            const int indentAmount = 2;

            void WriteLine(string text)
            {
                sb.Append(new string(' ', indent)).AppendLine(text);
            }

            WriteLine(".locals init (");
            indent += indentAmount * 2;
            for (var index = 0; index < mb.Variables.Count; index++)
            {
                var variableDefinition = mb.Variables[index];
                WriteLine($"{variableDefinition.VariableType.FullName} V_{index}");
            }

            indent -= indentAmount * 2;
            WriteLine(")");

            var handlerStack = new Stack <string>();

            foreach (var ins in instrs)
            {
                var blocks = exBlocks.GetValueSafe(ins) ?? new List <ExceptionBlock>();

                // Force exception close to the start for correct output
                blocks.Sort((a, b) => a.blockType == ExceptionBlockType.EndExceptionBlock ? -1 : 0);

                foreach (var exceptionBlock in blocks)
                {
                    switch (exceptionBlock.blockType)
                    {
                    case ExceptionBlockType.BeginExceptionBlock:
                        WriteLine(".try");
                        WriteLine("{");
                        indent += indentAmount;
                        handlerStack.Push(".try");
                        break;

                    case ExceptionBlockType.BeginCatchBlock:
                        WriteLine($"catch {exceptionBlock.catchType.FullName}");
                        WriteLine("{");
                        indent += indentAmount;
                        handlerStack.Push("handler (catch)");
                        break;

                    case ExceptionBlockType.BeginExceptFilterBlock:
                        WriteLine("filter");
                        WriteLine("{");
                        indent += indentAmount;
                        handlerStack.Push("handler (filter)");
                        break;

                    case ExceptionBlockType.BeginFaultBlock:
                        WriteLine("fault");
                        WriteLine("{");
                        indent += indentAmount;
                        handlerStack.Push("handler (fault)");
                        break;

                    case ExceptionBlockType.BeginFinallyBlock:
                        WriteLine("finally");
                        WriteLine("{");
                        indent += indentAmount;
                        handlerStack.Push("handler (finally)");
                        break;

                    case ExceptionBlockType.EndExceptionBlock:
                        indent -= indentAmount;
                        WriteLine($"}} // end {handlerStack.Pop()}");
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                var operand = ins.Operand;

                if (operand is ILLabel label)
                {
                    ins.Operand = label.Target;
                }
                else if (operand is ILLabel[] labels)
                {
                    ins.Operand = labels.Select(l => l.Target).ToArray();
                }

                WriteLine(ins.ToString());

                ins.Operand = operand;
            }

            return(sb.ToString());
        }
예제 #18
0
 public void AddEvent(ILConversion conversion, ExceptionBlockEventKind eventKind, ExceptionHandlingInfo handlingInfo, int offset, ExceptionBlock exceptionBlock)
 {
     AddEvent(conversion, eventKind, handlingInfo, offset, exceptionBlock, null);
 }
예제 #19
0
        public void AddEvent(ILConversion conversion, ExceptionBlockEventKind eventKind, ExceptionHandlingInfo handlingInfo, int offset, ExceptionBlock exceptionBlock, ExceptionHandler exceptionHandler)
        {
            var entry = new ExceptionBlockEventEntry()
            {
                ExceptionBlock   = exceptionBlock,
                Kind             = eventKind,
                Offset           = offset,
                ExceptionHandler = exceptionHandler
            };

            if (!handlingInfo.Events.TryGetValue(offset, out List <ExceptionBlockEventEntry> eventList))
            {
                eventList = new List <ExceptionBlockEventEntry>();

                handlingInfo.Events.Add(offset, eventList);
            }

            eventList.Add(entry);
        }
예제 #20
0
        /// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginFinallyBlock(Sigil.ExceptionBlock)" />
        public EmitShorthand BeginFinallyBlock(ExceptionBlock forTry, out FinallyBlock forFinally)
        {
            forFinally = BeginFinallyBlock(forTry);

            return(this);
        }
예제 #21
0
 private static string ExceptionBlockToString(ExceptionBlock block)
 {
     return($"{block.blockType}|{block.catchType.AssemblyQualifiedName}");
 }
예제 #22
0
 /// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginCatchBlock``1(Sigil.ExceptionBlock)" />
 public CatchBlock BeginCatchBlock <ExceptionType>(ExceptionBlock forTry)
 {
     return(BeginCatchBlock(forTry, typeof(ExceptionType)));
 }
예제 #23
0
        /// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginCatchBlock``1(Sigil.ExceptionBlock)" />
        public EmitShorthand BeginCatchBlock <ExceptionType>(ExceptionBlock forTry, out CatchBlock tryCatch)
        {
            tryCatch = BeginCatchBlock <ExceptionType>(forTry);

            return(this);
        }
예제 #24
0
 public void EndExceptionBlock(ExceptionBlock block)
 {
     EndHandler(block, block.cur);
 }
예제 #25
0
 /// <summary>
 /// Deep-copies the exception block.
 /// </summary>
 /// <param name="block">The exception block to clone.</param>
 /// <returns>The cloned exception block.</returns>
 public static ExceptionBlock Clone(this ExceptionBlock block)
 {
     return(new ExceptionBlock(block.blockType, block.catchType));
 }
예제 #26
0
        /// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginExceptionBlock" />
        public EmitShorthand BeginExceptionBlock(out ExceptionBlock forTry)
        {
            forTry = BeginExceptionBlock();

            return(this);
        }
예제 #27
0
        /// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.EndExceptionBlock(Sigil.ExceptionBlock)" />
        public EmitShorthand EndExceptionBlock(ExceptionBlock forTry)
        {
            InnerEmit.EndExceptionBlock(forTry);

            return(this);
        }
예제 #28
0
 public virtual T Visit(ExceptionBlock node)
 {
     Visit((Statement)node);
     traverse(node.onList);
     return(traverse(node.@default));
 }
예제 #29
0
        /// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginCatchBlock(System.Type, Sigil.ExceptionBlock)" />
        public EmitShorthand BeginCatchBlock(ExceptionBlock forTry, Type exceptionType, out CatchBlock forCatch)
        {
            forCatch = BeginCatchBlock(forTry, exceptionType);

            return(this);
        }
예제 #30
0
 /// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginCatchBlock(System.Type, Sigil.ExceptionBlock)" />
 public CatchBlock BeginCatchBlock(ExceptionBlock forTry, Type exceptionType)
 {
     return(InnerEmit.BeginCatchBlock(forTry, exceptionType));
 }
예제 #31
0
 /// <summary cref="M:Sigil.Emit.NonGeneric.Emit`1.BeginFinallyBlock(Sigil.ExceptionBlock)" />
 public FinallyBlock BeginFinallyBlock(ExceptionBlock forTry)
 {
     return(InnerEmit.BeginFinallyBlock(forTry));
 }