File: MethodBodyExtensions.cs
Web Access
Project: src\src\Controls\src\Build.Tasks\Controls.Build.Tasks.csproj (Microsoft.Maui.Controls.Build.Tasks)
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
 
namespace Microsoft.Maui.Controls.Build.Tasks
{
	static class MethodBodyExtensions
	{
		public static void Optimize(this MethodBody self)
		{
			if (self == null)
				throw new ArgumentNullException(nameof(self));
 
			self.OptimizeLongs();
			self.OptimizeStLdLoc();
			self.RemoveUnusedLocals();
			self.OptimizeMacros();
		}
 
		static void ExpandMacro(Instruction instruction, OpCode opcode, object operand)
		{
			instruction.OpCode = opcode;
			instruction.Operand = operand;
		}
 
		//this can be removed if/when https://github.com/jbevain/cecil/pull/307 is released in a nuget we consume
		static void OptimizeLongs(this MethodBody self)
		{
			for (var i = 0; i < self.Instructions.Count; i++)
			{
				var instruction = self.Instructions[i];
				if (instruction.OpCode.Code != Code.Ldc_I8)
					continue;
				var l = (long)instruction.Operand;
				if (l < int.MinValue || l > int.MaxValue)
					continue;
				ExpandMacro(instruction, OpCodes.Ldc_I4, unchecked((int)l));
				self.Instructions.Insert(++i, Instruction.Create(OpCodes.Conv_I8));
			}
		}
 
		static void OptimizeStLdLoc(this MethodBody self)
		{
			var method = self.Method;
			for (var i = 0; i < self.Instructions.Count; i++)
			{
				var instruction = self.Instructions[i];
				if (instruction.OpCode.Code != Code.Stloc)
					continue;
				if (i + 1 >= self.Instructions.Count)
					continue;
				var next = self.Instructions[i + 1];
				int num = ((VariableDefinition)instruction.Operand).Index;
				var vardef = instruction.Operand;
				if (next.OpCode.Code != Code.Ldloc || num != ((VariableDefinition)next.Operand).Index)
					continue;
				ExpandMacro(instruction, OpCodes.Dup, null);
				ExpandMacro(next, OpCodes.Stloc, vardef);
			}
		}
 
		static void RemoveUnusedLocals(this MethodBody self)
		{
			//Count ldloc for each variable
			var ldlocUsed = new List<VariableDefinition>();
			foreach (var instruction in self.Instructions)
			{
				if (instruction.OpCode.Code != Code.Ldloc)
					continue;
				var varDef = (VariableDefinition)instruction.Operand;
				if (!ldlocUsed.Contains(varDef))
					ldlocUsed.Add(varDef);
			}
 
			foreach (var varDef in self.Variables.ToArray())
			{
				if (ldlocUsed.Contains(varDef))
					continue;
 
				//find the Stloc instruction
				var instruction = (from instr in self.Instructions where instr.OpCode.Code == Code.Stloc && instr.Operand == varDef select instr).First();
 
				//remove dup/stloc
				if (instruction.Previous.OpCode.Code != Code.Dup)
					break;
 
				self.Instructions.Remove(instruction.Previous);
				self.Instructions.Remove(instruction);
 
				//and remove the variable
				self.Variables.Remove(varDef);
			}
		}
	}
}