Reputation: 63845
I'm writing some custom IL and need something equivalent to return SomeStaticField != null;
. This was my natural conclusion:
volatile.ldsfld ...SomeStaticField //volatile is needed here for unrelated reasons
ldnull
ceq
not
ret
However, this doesn't seem to work. I confirmed that SomeStaticField is null, but yet this function will end up returning true. I know C# uses branches for such a construct, and I could use it too, but it baffles me as to why this wouldn't have the expected behavior
A complete and verifiable example (as a library):
.assembly extern /*23000001*/ mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly 'BareMetal'
{
.custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() = (
01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module BareMetal.dll
.namespace Earlz.BareMetal
{
.class public auto ansi abstract sealed beforefieldinit BareMetal
extends [mscorlib]System.Object
{
.method public static hidebysig
default bool FooTest () cil managed
{
.maxstack 2
ldnull
ldnull
ceq
not
ret
}
}
}
Upvotes: 3
Views: 593
Reputation: 28789
not
computes the bitwise complement of its operand: ~1
is -2
, which, being non-zero, is true. The canonical way of negating a boolean is ldc.i4.0 ; ceq
.
And, as @HansPassant pointed out, the canonical way of doing a != null
comparison directly is cgt.un
-- all valid references are "greater than zero" when interpreted as unsigned values. That such comparisons are safe is explicitly documented in ECMA-335, section I.12.1.5:
In particular, object references can be:
...
- Created as a null reference (
ldnull
)...
Managed pointers have several additional base operations.
...
- Unsigned comparison and conditional branches based on two managed pointers (
bge.un
,bge.un.s
,bgt.un
,bgt.un.s
,ble.un
,ble.un.s
,blt.un
,blt.un.s
,cgt.un
,clt.un
).
Upvotes: 6