Sign in to follow this  
Trillian

[.net] && operator in MSIL

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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 =).

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this