L
Leon Lambert
I would appreciate it if someone could help me understand NaN handling
with respect to conditionals in IL code. I am playing with a small IL
interpreter and having a little problem with it. Following is a small
piece of C# code that gets compiled by VS2005 to simulate my problem.
static void Main(string[] args)
{
Double db1 = 1.0;
Double db2 = Double.NaN;
if (db1 <= db2)
db2 = 1.0;
}
This is very simple code. The assignment after the conditional should
never happen because the conditional should evaluate as false because of
the NaN. Following is the IL code generated.
..method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() =
( 01 00 00 00 )
// Code size 40 (0x28)
.maxstack 2
.locals init ([0] float64 db1,
[1] float64 db2,
[2] bool CS$4$0000)
IL_0000: nop
IL_0001: ldc.r8 1.
IL_000a: stloc.0
IL_000b: ldc.r8 (00 00 00 00 00 00 F8 FF)
IL_0014: stloc.1
IL_0015: ldloc.0
IL_0016: ldloc.1
IL_0017: cgt.un
IL_0019: stloc.2
IL_001a: ldloc.2
IL_001b: brtrue.s IL_0027
IL_001d: ldc.r8 1.
IL_0026: stloc.1
IL_0027: ret
} // end of method CABlock::Main
The IL code loads the two numbers onto the stack and does a cgt.un. This
should and does return a 0 (false) because of the NaN. The specification
is clear on this. The problem I am having is with the brtrue.s
instruction. The logic here seems to be reversed. If false is the result
of the cgt.un then the btrue will not branch which it should. This has
got me greatly confused. I have tried reading the CLR specification to
see what it does because it magically handles this properly. Somehow the
logic needs to get reversed but it is eluding me. The literal
interpretation of the above IL code only fails if there is a NaN
included. Without NaNs i have no problems at all.
Any help understanding the reversal of condition logic would be appreciated.
Leon Lambert
with respect to conditionals in IL code. I am playing with a small IL
interpreter and having a little problem with it. Following is a small
piece of C# code that gets compiled by VS2005 to simulate my problem.
static void Main(string[] args)
{
Double db1 = 1.0;
Double db2 = Double.NaN;
if (db1 <= db2)
db2 = 1.0;
}
This is very simple code. The assignment after the conditional should
never happen because the conditional should evaluate as false because of
the NaN. Following is the IL code generated.
..method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() =
( 01 00 00 00 )
// Code size 40 (0x28)
.maxstack 2
.locals init ([0] float64 db1,
[1] float64 db2,
[2] bool CS$4$0000)
IL_0000: nop
IL_0001: ldc.r8 1.
IL_000a: stloc.0
IL_000b: ldc.r8 (00 00 00 00 00 00 F8 FF)
IL_0014: stloc.1
IL_0015: ldloc.0
IL_0016: ldloc.1
IL_0017: cgt.un
IL_0019: stloc.2
IL_001a: ldloc.2
IL_001b: brtrue.s IL_0027
IL_001d: ldc.r8 1.
IL_0026: stloc.1
IL_0027: ret
} // end of method CABlock::Main
The IL code loads the two numbers onto the stack and does a cgt.un. This
should and does return a 0 (false) because of the NaN. The specification
is clear on this. The problem I am having is with the brtrue.s
instruction. The logic here seems to be reversed. If false is the result
of the cgt.un then the btrue will not branch which it should. This has
got me greatly confused. I have tried reading the CLR specification to
see what it does because it magically handles this properly. Somehow the
logic needs to get reversed but it is eluding me. The literal
interpretation of the above IL code only fails if there is a NaN
included. Without NaNs i have no problems at all.
Any help understanding the reversal of condition logic would be appreciated.
Leon Lambert