[.net] && operator in MSIL

This topic is 3716 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

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 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 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 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.

1. 1
2. 2
Rutin
17
3. 3
4. 4
5. 5

• 13
• 26
• 10
• 11
• 9
• Forum Statistics

• Total Topics
633735
• Total Posts
3013597
×