I'm trying to understand how a while loop looks in IL. I have written this C# function:
    static void Brackets()
    {
        while (memory[pointer] > 0)
        {
            // Snipped body of the while loop, as it's not important
        }
    } 
The IL looks like this:
.method private hidebysig static void  Brackets() cil managed
{
  // Code size       37 (0x25)
  .maxstack  2
  .locals init ([0] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  br.s       IL_0012
  IL_0003:  nop
  // Snipped body of the while loop, as it's not important
  IL_0011:  nop
  IL_0012:  ldsfld     uint8[] BFHelloWorldCSharp.Program::memory
  IL_0017:  ldsfld     int16 BFHelloWorldCSharp.Program::pointer
  IL_001c:  ldelem.u1
  IL_001d:  ldc.i4.0
  IL_001e:  cgt
  IL_0020:  stloc.0
  IL_0021:  ldloc.0
  IL_0022:  brtrue.s   IL_0003
  IL_0024:  ret
} // end of method Program::Brackets
For the most part this is really simple, except for the part after cgt.
What I don't understand is the local [0] and the stloc.0/ldloc.0. As far as I see it, cgt pushes the result to the stack, stloc.0 gets the result from the stack into the local variable, ldloc.0 pushes the result to the stack again and brtrue.s reads from the stack.
What is the purpose of doing this? Couldn't this be shortened to just cgt followed by brtrue.s?
Try compiling with optimizations.
That is a debug build (from the nop). All bets are off, but it looks like it is simply introducing a bool variable for simplicity:
    goto testforexit;
body:
    ..
testforexit:
    bool tmp = memory[pointer] > 0;
    if(tmp) goto body;
Build in release with optimisations enabled, which should remove such variables.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With