Click here to Skip to main content
15,868,164 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
I am mucking around with parsing some IL at the moment, and I just so happened upon the IL generated from a very simple lambda function in my code. The original code looks like this:
C#
((User x) => x.Id == 2) // this is a lambda function from a Where call


The IL generated from this C# code looks like so:
C#
IL_0000: ldarg.0
IL_0001: callvirt instance int32 Utilities.Test.User::get_Id()
IL_0006: ldc.i4.2
IL_0007: ceq
IL_0009: stloc.0
IL_000a: br.s IL_000c  // originally "br.s 0"
IL_000c: ldloc.0
IL_000d: ret


I get most of it - it loads the User parameter 'x' onto the stack, calls the getter of the Id property chucks the result on the stack, chucks a two on the stack, then checks for equality.

So, 'ceq' places this boolean result onto the stack. So this is what I read from addresses IL_0009 onwards:
IL_0009: pop the result of the ceq evaluation off the stack into local var 0
IL_000a: branch 0 instructions forward
IL_000c: load the local var 0 back onto the stack
IL_000d: return


I can't see how instructions 9 through C are relevant, is there something that the seemingly pointless "branch 0" call is doing that I am completely misunderstanding here? Is there some side-effect of branching that is useful here?

Any help is appreciated :)

EDIT: I keep reading this and catch myself thinking it's native code, I forget these instructions aren't executed directly on the CPU. So maybe a branch command in IL is replaced by the JITter with some x86 instruction like 'jmp' that clears flags registers set in the ceq function that could cause problems after returning from the function... like it's 'cleaning up after itself' with the side-effects of a jump.

Really I have no idea, I'm clutching at straws here...
Posted
Updated 12-Sep-11 19:05pm
v3
Comments
Mehdi Gholam 12-Sep-11 11:39am    
Are compiling in debug or release mode?
GlobX 12-Sep-11 19:40pm    
Ah, hadn't thought of that, it's in debug mode. So is this code there to facilitate a breakpoint or something?
Pravin Patil, Mumbai 13-Sep-11 1:24am    
I think you are correct. Because VS debugger, with the help of .pdb file, maps the breakpoint to execution address. Also, in the debug IL debug symbols are not omitted while in release mode they are totally omitted. So the two build viz. debug and release will never be the same.
GlobX 13-Sep-11 1:53am    
Interesting, although a little anti-climactic :) I should've realised that I was in debug mode straight away... Anyway, good to know.

I will keep searching and if I find an in-depth explanation somewhere I shall add it here.

1 solution

Confirmed that this was an artifact of debug mode, this is the Release IL:

C#
IL_0000: ldarg.0
IL_0001: callvirt instance int32 Collabowrite.Utilities.Test.User::get_Id()
IL_0006: ldc.i4.2
IL_0007: ceq // no crazy instructions below!
IL_0009: ret


This is no confirmation of whether it was to facilitate breakpoints or otherwise, but at this point this seems like the most likely explanation.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900