private void ProcessBody(MethodDefinition method) { if (method.IsAsyncStateMachine()) { LogTo.Information("Async method '{0}' cannot be modified by Usable.", method.FullName); return; } method.Body.SimplifyMacros(); var ilProcessor = method.Body.GetILProcessor(); if (method.Body.Instructions.Last().OpCode == OpCodes.Throw) { ilProcessor.Append(ilProcessor.Create(OpCodes.Ret)); } method.Body.OptimizeMacros(); method.Body.SimplifyMacros(); var ilMethod = Decompile(method); var visitor = new UsableVisitor(method); visitor.Visit(ilMethod); if (!visitor.UsingRanges.Any()) { method.Body.OptimizeMacros(); return; } // Convert early returns to branches to the last return if (visitor.EarlyReturns.Any() && method.Body.Instructions.Last().OpCode == OpCodes.Ret) { FixEarlyReturns(method.Body, visitor.EarlyReturns); } // Inserts nops to ensure nested trys are not overlapping var usingBlocks = FixUsingBlocks(ilProcessor, visitor.UsingRanges .Select(r => Tuple.Create(method.Body.Instructions.AtOffset(r.From), method.Body.Instructions.BeforeOffset(r.To))) .ToList()); // Add the usings foreach (var usingBlock in usingBlocks.OrderBy(u => u.Item1.Offset)) { AddUsing(method.Body, usingBlock); } method.Body.OptimizeMacros(); method.Body.SimplifyMacros(); // Sort exception handlers so inner trys are before outer ones method.Body.ExceptionHandlers.ReplaceCollection(method.Body.ExceptionHandlers.OrderBy(x => x, new ExceptionHandlerComparer())); // Any branches in a try branching to outside must be converted to leaves foreach (var handler in method.Body.ExceptionHandlers) { ReplaceBranchesWithLeaves(ilProcessor, handler); } method.Body.OptimizeMacros(); }
private void ProcessBody(MethodDefinition method) { if (method.IsAsyncStateMachine()) { LogTo.Information("Async method '{0}' cannot be modified by Usable.", method.FullName); return; } method.Body.SimplifyMacros(); var ilProcessor = method.Body.GetILProcessor(); if (method.Body.Instructions.Last().OpCode == OpCodes.Throw) ilProcessor.Append(ilProcessor.Create(OpCodes.Ret)); method.Body.OptimizeMacros(); method.Body.SimplifyMacros(); var ilMethod = Decompile(method); var visitor = new UsableVisitor(method); visitor.Visit(ilMethod); if (!visitor.UsingRanges.Any()) { method.Body.OptimizeMacros(); return; } // Convert early returns to branches to the last return if (visitor.EarlyReturns.Any() && method.Body.Instructions.Last().OpCode == OpCodes.Ret) FixEarlyReturns(method.Body, visitor.EarlyReturns); // Inserts nops to ensure nested trys are not overlapping var usingBlocks = FixUsingBlocks(ilProcessor, visitor.UsingRanges .Select(r => Tuple.Create(method.Body.Instructions.AtOffset(r.From), method.Body.Instructions.BeforeOffset(r.To))) .ToList()); // Add the usings foreach (var usingBlock in usingBlocks.OrderBy(u => u.Item1.Offset)) AddUsing(method.Body, usingBlock); method.Body.OptimizeMacros(); method.Body.SimplifyMacros(); // Sort exception handlers so inner trys are before outer ones method.Body.ExceptionHandlers.ReplaceCollection(method.Body.ExceptionHandlers.OrderBy(x => x, new ExceptionHandlerComparer())); // Any branches in a try branching to outside must be converted to leaves foreach (var handler in method.Body.ExceptionHandlers) ReplaceBranchesWithLeaves(ilProcessor, handler); method.Body.OptimizeMacros(); }