[quoted text, click to view] "Ben Voigt" <rbv@nospam.nospam> wrote in message
news:evAJyTrmGHA.3752@TK2MSFTNGP02.phx.gbl...
Found it in the CIL Spec Part 3:
1.7.5 Backward Branch Constraints
It must be possible, with a single forward-pass through the CIL instruction
stream for any method, to infer the exact state of the evaluation stack at
every instruction (where by "state" we mean the number and type of each item
on the evaluation stack).
In particular, if that single-pass analysis arrives at an instruction, call
it location X, that immediately follows an unconditional branch, and where X
is not the target of an earlier branch instruction, then the state of the
evaluation stack at X, clearly, cannot be derived from existing information.
In this case, the CLI demands that the evaluation stack at X be empty.
Following on from this rule, it would clearly be invalid CIL if a later
branch instruction to X were to have a non-empty evaluation stack
The spec uses the word invalid. So, is my code not only unverifiable but
also illegal? However, I think I can deal with this with an unreachable
instruction setting the correct stack depth.
[quoted text, click to view] >
> The method initializes a BitArray field from an array of indexes to be set
> (MyClass/Bits is an enum)
> Here's the MSIL viewed with reflector (annotated with the stack height
> before/after the instruction):
> .method public specialname rtspecialname instance void .ctor([in]
> MyClass/Bits[] bits) cil managed
> {
> .param [1]
> .custom instance void [mscorlib]System.ParamArrayAttribute::.ctor()
> .maxstack 6
> .locals init (
> [0] [mscorlib]System.Collections.BitArray array1,
> [1] int32 num1)
> 0/1 L_0000: ldarg.0
> 1/2 L_0001: ldc.i4 16
> 2/2 L_0006: newobj instance void
> [mscorlib]System.Collections.BitArray::.ctor(int32)
> 2/3 L_000b: ldarg.1
> 3/2 L_000c: brfalse L_002f
> 2/1 L_0011: stloc.0
> 1/2 L_0012: ldarg.1
> 2/2 L_0013: ldlen
> 2/1 L_0014: stloc.1
> 1/1 L_0015: br L_0028
> # warning occurs here
> 1/2 L_001a: ldloc.1
> 2/3 L_001b: ldc.i4.1
> 3/2 L_001c: sub
> 2/1 L_001d: stloc.1
> 1/2 L_001e: ldloc.0
> 2/3 L_001f: ldarg.1
> 3/4 L_0020: ldloc.1
> 4/3 L_0021: ldelem.i4
> 3/4 L_0022: ldc.i4.1
> 4/1 L_0023: callvirt instance void
> [mscorlib]System.Collections.BitArray::Set(int32, bool)
> 1/2 L_0028: ldloc.1
> 2/1 L_0029: brtrue L_001a
> 1/2 L_002e: ldloc.0
> 2/0 L_002f: stfld [mscorlib]System.Collections.BitArray
> MyClass::internalValue
> 0/* L_0034: ret
> }
>
> What's more, even if PEVerify makes a linear pass, instead of following
> unconditional branches, the constraint still holds (although I think I can
> knock one instruction off if I relax that.
>
> Are unconditional forward branches forbidden?
>