Reflection emit stack and method call
Asked Answered
P

2

5

Can someone explain to me what needs to be loaded into the stack prior to making a function call via reflection.emit?

I have a very simple method

public static void Execute(string 1, string 2)

I want to generate the method in the following class dynamically (forget the rest, I got them sorted out)

public class Test{
    public string s1;

    public void Run(string s2)
    {
        MyOtherClass.Execute(s2,s1)
    }
}

I have a copy of the above test, for reference, and I noticed the following opcodes were emitted, prior to the "call".

  1. ldarg_1
  2. ldarg_0
  3. ldfld

The question is what's ldarg_0 doing there? I only need 2 arguments for the call, why does the CLR requires ldarg_0 to be pushed to the stack?

Perishing answered 11/1, 2013 at 1:37 Comment(1)
Can you provide the surrounding IL?Pebbly
C
9

arg.0 contains this and is required by ldfld string Test:s1 to push this.s1 onto the stack.

.method public hidebysig instance void Run(string s2) cil managed
{
    .maxstack 8                                      // maximum stack size 8
    ldarg.1                                          // push argument s2
    ldarg.0                                          // push this
    ldfld string Test::s1                            // pop this, push this.s1
    call void MyOtherClass::Execute(string, string)  // call
    ret                                              // return
}
Ceiba answered 11/1, 2013 at 1:58 Comment(1)
Thank you! I know what I missed now.Perishing
Z
2

You need to push the method's arguments in order of declaration and an object reference if the method is not static. In your test case, you are accessing a member field (s1), so you need the this reference for it. That's what ldarg_0 provides. The subsequent ldfld pops the this reference and pushes the field's value onto the evaluation stack.

Ziguard answered 11/1, 2013 at 1:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.