What IL instructions are not exposed by C#?
I'm referring to instructions like sizeof and cpblk - there's no class or command that executes these instructions (sizeof in C# is computed at compile time, not at runtime AFAIK).
Others?
EDIT: The reason I'm asking this (and hopefully this will make my question a little more valid) is because I'm working on a small library which will provide the functionality of these instructions. sizeof and cpblk are already implemented - I wanted to know what others I may have missed before moving on.
EDIT2: Using Eric's answer, I've compiled a list of instructions:
There were a number of other instructions which were not included in the list, which I'm separating because they're basically shortcuts for other instructions (compressed to save time and space):
I'm referring to instructions like sizeof and cpblk - there's no class or command that executes these instructions (sizeof in C# is computed at compile time, not at runtime AFAIK).
This is incorrect. sizeof(int)
will be treated as the compile-time constant 4, of course, but there are plenty of situations (all in unsafe
code) where the compiler relies upon the runtime to determine what the memory size of a structure is. Consider, for example, a structure that contains two pointers. It would be of size 8 on a 32 bit machine but 16 on a 64 bit machine. In those circumstances the compiler will generate the sizeof opcode.
Others?
I don't have a list of all the opcodes we don't produce -- I have never had a need to build such a list. However, off the top of my head I can tell you that there is no way to generate an "call indirect" (calli) instruction in C#; we are occasionally asked for that feature as it would improve performance of certain interop scenarios.
UPDATE: I just grepped the source code to produce a list of opcodes we definitely do produce. They are:
add
add_ovf
add_ovf_un
and
arglist
beq
beq_s
bge
bge_s
bge_un
bge_un_s
bgt
bgt_s
bgt_un
bgt_un_s
ble
ble_s
ble_un
ble_un_s
blt
blt_s
blt_un
blt_un_s
bne_un
bne_un_s
box
br
br_s
brfalse
brfalse_s
brtrue
brtrue_s
call
callvirt
castclass
ceq
cgt
cgt_un
clt
clt_un
constrained
conv_i
conv_ovf_i
conv_ovf_i_un
conv_ovf_u
conv_ovf_u_un
conv_r
conv_r_un
conv_u
div
div_un
dup
endfinally
initobj
isinst
ldarg
ldarg_
ldarg_s
ldarga
ldarga_s
ldc_i
ldc_r
ldelem
ldelem_i
ldelem_r
ldelem_ref
ldelem_u
ldelema
ldfld
ldflda
ldftn
ldind_i
ldind_r
ldind_ref
ldind_u
ldlen
ldloc
ldloc_
ldloc_s
ldloca
ldloca_s
ldnull
ldobj
ldsfld
ldsflda
ldstr
ldtoken
ldvirtftn
leave
leave_s
localloc
mkrefany
mul
mul_ovf
mul_ovf_un
neg
newarr
newobj
nop
not
or
pop
readonly
refanytype
refanyval
rem
rem_un
ret
rethrow
shl
shr
shr_un
sizeof
starg
starg_s
stelem
stelem_i
stelem_r
stelem_ref
stfld
stind_i
stind_r
stind_ref
stloc
stloc_s
stobj
stsfld
sub
sub_ovf
sub_ovf_un
switch
throw
unbox_any
volatile
xor
I'm not going to guarantee that that's all of them, but that is certainly most of them. You can then compare that against a list of all the opcodes and see what is missing.