I am using Mono.Cecil to do some analysis and rewriting on an assembly. In some cases this is pretty easy: you can just look right before the call to see where the arguments are loaded:
// Math.Pow(2, 4)
IL_0001: ldc.r8 00 00 00 00 00 00 00 40
IL_000A: ldc.r8 00 00 00 00 00 00 10 40
IL_0013: call System.Math.Pow
However, this gets more complicated when the arguments to the function are themselves complex expressions:
// Math.Pow(2, Math.Abs(Math.Max(17, "123".GetHashCode())));
IL_0001: ldc.r8 00 00 00 00 00 00 00 40
IL_000A: ldc.i4.s 11
IL_000C: ldstr "123"
IL_0011: callvirt System.Object.GetHashCode
IL_0016: call System.Math.Max
IL_001B: call System.Math.Abs
IL_0020: conv.r8
IL_0021: call System.Math.Pow
In this case, a bunch of stuff happens between when the first argument is loaded and when the second argument is loaded. I'm wondering: does Mono.Cecil expose any tools for finding the IL instructions responsible for pushing each argument?