2 using Mono.Cecil.Rocks;
5 using System.Collections.Generic;
7 namespace Tizen.NUI.Xaml.Build.Tasks
9 static class MethodBodyExtensions
11 public static void Optimize(this MethodBody self)
14 throw new ArgumentNullException(nameof(self));
17 self.OptimizeStLdLoc();
18 self.RemoveUnusedLocals();
19 self.OptimizeMacros();
22 static void ExpandMacro(Instruction instruction, OpCode opcode, object operand)
24 instruction.OpCode = opcode;
25 instruction.Operand = operand;
28 //this can be removed if/when https://github.com/jbevain/cecil/pull/307 is released in a nuget we consume
29 static void OptimizeLongs(this MethodBody self)
31 for (var i = 0; i < self.Instructions.Count; i++) {
32 var instruction = self.Instructions[i];
33 if (instruction.OpCode.Code != Code.Ldc_I8)
35 var l = (long)instruction.Operand;
36 if (l < int.MinValue || l > int.MaxValue)
38 ExpandMacro(instruction, OpCodes.Ldc_I4, unchecked((int)l));
39 self.Instructions.Insert(++i, Instruction.Create(OpCodes.Conv_I8));
43 static void OptimizeStLdLoc(this MethodBody self)
45 var method = self.Method;
46 for (var i = 0; i < self.Instructions.Count; i++) {
47 var instruction = self.Instructions[i];
48 if (instruction.OpCode.Code != Code.Stloc)
50 if (i + 1 >= self.Instructions.Count)
52 var next = self.Instructions[i + 1];
53 int num = ((VariableDefinition)instruction.Operand).Index;
54 var vardef = instruction.Operand;
55 if (next.OpCode.Code != Code.Ldloc || num != ((VariableDefinition)next.Operand).Index)
57 ExpandMacro(instruction, OpCodes.Dup, null);
58 ExpandMacro(next, OpCodes.Stloc, vardef);
62 static void RemoveUnusedLocals(this MethodBody self)
64 //Count ldloc for each variable
65 var ldlocUsed = new List<VariableDefinition>();
66 foreach (var instruction in self.Instructions) {
67 if (instruction.OpCode.Code != Code.Ldloc)
69 var varDef = (VariableDefinition)instruction.Operand;
70 if (!ldlocUsed.Contains(varDef))
71 ldlocUsed.Add(varDef);
74 foreach (var varDef in self.Variables.ToArray()) {
75 if (ldlocUsed.Contains(varDef))
78 //find the Stloc instruction
79 var instruction = (from instr in self.Instructions where instr.OpCode.Code == Code.Stloc && instr.Operand == varDef select instr).First();
82 if (instruction.Previous.OpCode.Code != Code.Dup)
85 self.Instructions.Remove(instruction.Previous);
86 self.Instructions.Remove(instruction);
88 //and remove the variable
89 self.Variables.Remove(varDef);