[.net] && operator in MSIL

Started by
2 comments, last by Drigovas 15 years, 6 months ago
Hello! I'm writing a C# compiler in C# for fun and I'm having some trouble with the && operator as to how it should be implemented. I'm using Red Gate's free .NET Reflector to check the MSIL my code generates. That tool can also decompile MSIL into C# but it fails to do so correctly with my && operator. Here's my code to generate the && operator: [EDIT] Sorry, I had posted the code of the || op.

            Label endLabel = IlGenerator.DefineLabel();
            LeftOperand.Emit(IlGenerator); // Pushes the (boolean) value of the operand
            IlGenerator.Emit(OpCodes.Dup);
            IlGenerator.Emit(OpCodes.Brfalse_S, endLabel);
            IlGenerator.Emit(OpCodes.Pop);
            RightOperand.Emit(IlGenerator); // Pushes the (boolean) value of the operand
            IlGenerator.MarkLabel(endLabel);

In my compilation test case, I have the following code:
void Test()
{
	if (true && false) debugprint @"Hello World!"; // "debugprint" is a temporary keyword that calls Console.WriteLine until I implement method call parsing =)
}

The generated MSIL, as seen in the .NET Reflector, is:
.method public hidebysig static void Test() cil managed
{
    .maxstack 2
    L_0000: ldc.i4.1 
    L_0001: dup 
    L_0002: brfalse.s L_0006
    L_0004: pop 
    L_0005: ldc.i4.0 
    L_0006: brfalse.s L_0017
    L_0008: ldstr "Hello World!"
    L_000d: call void [mscorlib]System.Console::WriteLine(string)
    L_0012: br L_0017
    L_0017: ret 
}

But the decompiled C# appears as:
public static void Test()
{
    // This item is obfuscated and can not be translated.
    if (1 == 0)
    {
        goto Label_0006;
    }
    if (0 != 0)
    {
        Console.WriteLine("Hello World!");
    }
}

I suspect I'm not implementing the && operator the usual way, any ideas on what I'm doing wrong? Thanks! [Edited by - Trillian on October 13, 2008 11:11:02 AM]
Advertisement
Umm, what's wrong with that?

It looks horrid and the logic is weird, but if you change it to true&&true you should get
if(1==0){    goto end;}if(1!=0){    print;}


Which will correctly print. And false for the first matches 0==0 causing it to goto end...
Actually I knew that the logic works as I had tested it. But the way the .NET reflector decompiled it made me think that maybe I was doing the && in an unorthodox way. I wanted to know if there was a more "standard" way to implement that operator.

I had a look at what MSVC# generated for a similar block of code and tried to mimick its logic like this:

Label leftOperandFalseLabel = IlGenerator.DefineLabel();Label endLabel = IlGenerator.DefineLabel();LeftOperand.Emit(IlGenerator);IlGenerator.Emit(OpCodes.Brfalse_S, leftOperandFalseLabel);RightOperand.Emit(IlGenerator);IlGenerator.Emit(OpCodes.Br_S, endLabel);IlGenerator.MarkLabel(leftOperandFalseLabel);IlGenerator.Emit(OpCodes.Ldc_I4_1);IlGenerator.MarkLabel(endLabel);


But the decompiler generated the following:
if (((1 == 0) ? 0 : 0) != 0){    Console.WriteLine("Hello World!");}

... which is not really better.

So I guess there's no "standard" way to implement the && operator and I should stop relying too much on this tool... Ah well, it was good while it lasted =).
Pretty much all modern ways of representing the && and || operators are done in this way, there is nothing wrong with what you are seeing. Since they compile down to the same instructions, it is understandable that a decompiler would have some difficulty with differentiating the statements you are compiling and the statements it is decompiling to. The low level representation like MSIL doesn't have any concept for these sort of large boolean equations that you see in lots of if() statements, so what you get is a decomposition into a sequence of single statements that are each evaluated independently.

This topic is closed to new replies.

Advertisement