I am researching IL code which generated from this C# code (RELEASE):
int a = Convert.ToInt32(Console.ReadLine());
switch(a)
{
case 1: Console.WriteLine(); break;
case 2: Console.WriteLine(); break;
case 3: Console.WriteLine(); break;
case 15: Console.WriteLine(); break;
default: Console.WriteLine(); break;
}
IL:
//Why not "switch(IL_0026, IL_002c, IL_0032, IL_0038)"?
IL_000e: switch (IL_0026, IL_002c, IL_0032)
IL_001f: ldloc.0
IL_0020: ldc.i4.s 15
IL_0022: beq.s IL_0038
IL_0024: br.s IL_003e
IL_0026: call void [System.Console]System.Console::WriteLine()
IL_002b: ret
IL_002c: call void [System.Console]System.Console::WriteLine()
IL_0031: ret
IL_0032: call void [System.Console]System.Console::WriteLine()
IL_0037: ret
IL_0038: call void [System.Console]System.Console::WriteLine()
IL_003d: ret
IL_003e: call void [System.Console]System.Console::WriteLine()
IL_0043: ret
Why "switch" in IL works with sequence (1,2,3... n 1) and do not add other values (for exapmle: for 15 generated 3 instruction (001f, 0020, 0022))
CodePudding user response:
//Why not "switch(IL_0026, IL_002c, IL_0032, IL_0038)"?
Because that 4th label would be jumped to if the value of a
was 4, not 15. The jump targets in a switch
correspond to successive values of the tested value.
In order to use switch
and not have the additional special case for 15
, it would need to be:
switch(IL_0026, IL_002c, IL_0032, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_0038)
(I hope I've counted right)
Which would be a much larger jump table.
I'd always recommend checking out the documentation for Reflection.Emit
for the instruction you're looking at, e.g. OpCodes.Switch
, to make sure you understand what the instruction does.
The switch instruction pops a value off the stack and compares it, as an unsigned integer, to
N
. If value is less thanN
, execution is transferred to the target indexed by value, where targets are numbered from 0 (for example, a value of 0 takes the first target, a value of 1 takes the second target, and so on).