예제 #1
0
        internal static void EmitMethod(IReadOnlyList <MsilInstruction> source, LoggingIlGenerator target)
        {
            var instructions = source.ToArray();
            var offsets      = new int[instructions.Length];
            // Calc worst case offsets
            {
                var j = 0;
                for (var i = 0; i < instructions.Length; i++)
                {
                    offsets[i] = j;
                    j         += instructions[i].MaxBytes;
                }
            }

            // Perform label markup
            var targets = new Dictionary <MsilLabel, int>();

            for (var i = 0; i < instructions.Length; i++)
            {
                foreach (var label in instructions[i].Labels)
                {
                    if (targets.TryGetValue(label, out var other))
                    {
                        _log.Warn($"Label {label} is applied to ({i}: {instructions[i]}) and ({other}: {instructions[other]})");
                    }
                    targets[label] = i;
                }
            }

            // Simplify branch instructions
            for (var i = 0; i < instructions.Length; i++)
            {
                var existing = instructions[i];
                if (existing.Operand is MsilOperandBrTarget brOperand && _longToShortBranch.TryGetValue(existing.OpCode, out var shortOpcode))
                {
                    var targetIndex = targets[brOperand.Target];
                    var delta       = offsets[targetIndex] - offsets[i];
                    if (sbyte.MinValue < delta && delta < sbyte.MaxValue)
                    {
                        instructions[i] = instructions[i].CopyWith(shortOpcode);
                    }
                }
            }

            for (var i = 0; i < instructions.Length; i++)
            {
                MsilInstruction il = instructions[i];
                foreach (var tro in il.TryCatchOperations)
                {
                    switch (tro.Type)
                    {
                    case MsilTryCatchOperationType.BeginExceptionBlock:
                        target.BeginExceptionBlock();
                        break;

                    case MsilTryCatchOperationType.BeginClauseBlock:
                        target.BeginCatchBlock(tro.CatchType);
                        break;

                    case MsilTryCatchOperationType.BeginFaultBlock:
                        target.BeginFaultBlock();
                        break;

                    case MsilTryCatchOperationType.BeginFinallyBlock:
                        target.BeginFinallyBlock();
                        break;

                    case MsilTryCatchOperationType.EndExceptionBlock:
                        target.EndExceptionBlock();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                foreach (MsilLabel label in il.Labels)
                {
                    target.MarkLabel(label.LabelFor(target));
                }

                MsilInstruction ilNext = i < instructions.Length - 1 ? instructions[i + 1] : null;

                // Leave opcodes emitted by these:
                if (il.OpCode == OpCodes.Endfilter && ilNext != null &&
                    ilNext.TryCatchOperations.Any(x => x.Type == MsilTryCatchOperationType.BeginClauseBlock))
                {
                    continue;
                }
                if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S) && ilNext != null &&
                    ilNext.TryCatchOperations.Any(x => x.Type == MsilTryCatchOperationType.EndExceptionBlock ||
                                                  x.Type == MsilTryCatchOperationType.BeginClauseBlock ||
                                                  x.Type == MsilTryCatchOperationType.BeginFaultBlock ||
                                                  x.Type == MsilTryCatchOperationType.BeginFinallyBlock))
                {
                    continue;
                }
                if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S || il.OpCode == OpCodes.Endfinally) &&
                    ilNext != null && ilNext.TryCatchOperations.Any(x => x.Type == MsilTryCatchOperationType.EndExceptionBlock))
                {
                    continue;
                }
                if (il.OpCode == OpCodes.Endfinally && ilNext != null &&
                    ilNext.TryCatchOperations.Any(x => x.Type == MsilTryCatchOperationType.EndExceptionBlock))
                {
                    continue;
                }

                if (il.Operand != null)
                {
                    il.Operand.Emit(target);
                }
                else
                {
                    target.Emit(il.OpCode);
                }
            }
        }
예제 #2
0
        internal static void EmitMethod(IReadOnlyList <MsilInstruction> instructions, LoggingIlGenerator target)
        {
            for (var i = 0; i < instructions.Count; i++)
            {
                MsilInstruction il = instructions[i];
                if (il.TryCatchOperation != null)
                {
                    switch (il.TryCatchOperation.Type)
                    {
                    case MsilTryCatchOperationType.BeginExceptionBlock:
                        target.BeginExceptionBlock();
                        break;

                    case MsilTryCatchOperationType.BeginClauseBlock:
                        target.BeginCatchBlock(il.TryCatchOperation.CatchType);
                        break;

                    case MsilTryCatchOperationType.BeginFaultBlock:
                        target.BeginFaultBlock();
                        break;

                    case MsilTryCatchOperationType.BeginFinallyBlock:
                        target.BeginFinallyBlock();
                        break;

                    case MsilTryCatchOperationType.EndExceptionBlock:
                        target.EndExceptionBlock();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                foreach (MsilLabel label in il.Labels)
                {
                    target.MarkLabel(label.LabelFor(target));
                }

                MsilInstruction ilNext = i < instructions.Count - 1 ? instructions[i + 1] : null;

                // Leave opcodes emitted by these:
                if (il.OpCode == OpCodes.Endfilter && ilNext?.TryCatchOperation?.Type ==
                    MsilTryCatchOperationType.BeginClauseBlock)
                {
                    continue;
                }
                if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S) &&
                    (ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.EndExceptionBlock ||
                     ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginClauseBlock ||
                     ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginFaultBlock ||
                     ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginFinallyBlock))
                {
                    continue;
                }
                if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S || il.OpCode == OpCodes.Endfinally) &&
                    ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.EndExceptionBlock)
                {
                    continue;
                }

                if (il.Operand != null)
                {
                    il.Operand.Emit(target);
                }
                else
                {
                    target.Emit(il.OpCode);
                }
            }
        }