using dnlib.DotNet; using dnlib.DotNet.Emit; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace BMDevs.ControlFlow { public class BlockParser { public static List ParseMethod(MethodDef method) { List blocks = new List(); List body = new List(method.Body.Instructions); //splitting into blocks (Thanks to CodeOfDark#6320) Block block = new Block(); int Id = 0; int usage = 0; block.Number = Id; block.Instructions.Add(Instruction.Create(OpCodes.Nop)); blocks.Add(block); block = new Block(); Stack handlers = new Stack(); foreach (Instruction instruction in method.Body.Instructions) { foreach (var eh in method.Body.ExceptionHandlers) { if (eh.HandlerStart == instruction || eh.TryStart == instruction || eh.FilterStart == instruction) handlers.Push(eh); } foreach (var eh in method.Body.ExceptionHandlers) { if (eh.HandlerEnd == instruction || eh.TryEnd == instruction) handlers.Pop(); } int stacks, pops; instruction.CalculateStackUsage(out stacks, out pops); block.Instructions.Add(instruction); usage += stacks - pops; if (stacks == 0) { if (instruction.OpCode != OpCodes.Nop) { if ((usage == 0 || instruction.OpCode == OpCodes.Ret) && handlers.Count == 0) { block.Number = ++Id; blocks.Add(block); block = new Block(); } } } } return blocks; } } }