Facts:
-
The correct encoding for the CIL instruction
rethrow‘s op-code is the two-byte sequenceFE 1A. -
OpCodes.Rethrow.Value(which has typeshort) has value0xFE1Aon my little-endian machine. -
BitConverterhonours the machine’s endianness when converting to/from byte sequences. -
On my little-endian machine,
BitConverter.GetBytes(OpCodes.Rethrow.Value)results in the byte sequence1A FE.
That means, serializing an OpCode.Value on a little-endian machine using BitConverter does not produce the correct encoding for the op-code; the byte order is reversed.
Questions:
-
Is the byte ordering of
OpCode.Valuedocumented (and if so, where?), or is it an “implementation detail”? -
Does step 4 above on a big-endian machine also result in the wrong byte ordering? That is, would
OpCodes.Rethrow.Valuebe0x1AFEon a big-endian machine?
I’ve reached the conclusion that serializing an op-code representation based on the
OpCode.Valueproperty, i.e.:is a bad idea, but not because of the use of
BitConverter.GetBytes(short), whose behaviour is well-documented. The main culprit is theOpCode.Valueproperty, whose documentation is vague in two respects:It states that this property contains “the value of the immediate operand”, which may or may not refer to the op-code’s encoding; that term doesn’t appear anywhere in the CLI specification.
Even when we assume that it does in fact contain an op-code’s encoding, the documentation says nothing about byte order. (Byte order comes into play when converting between
byte[]andshort.)Why am I basing my argument on MSDN documentation, and not on the CLI standard? Because
System.Reflection.Emitis not part of the Reflection Library as defined by the CLI standard. For this reason, I think it’s fairly safe to say that the MSDN reference documentation for this namespace is as close as it gets to an official specification. (But unlike @Hans Passant’s answer, I would not take one step further and claim that the reference source is in any way a specification.)Conclusion:
There are two ways to output the op-code encoding for a given
OpCodeobject:Stay with
System.Reflection.Emitfunctionality and useILGenerator.Emit(someOpCode). This may be too restrictive in some situations.Create your own mapping between op-code encodings (i.e.
byte[]sequences) and the variousOpCodeobjects.