Инструкции IL, не представленные C # - PullRequest
33 голосов
/ 18 августа 2011

Какие инструкции IL не предоставляются C #?

Я имею в виду такие инструкции, как sizeof и cpblk - нет класса или команды, которая выполняет эти инструкции (sizeof в C # вычисляется во время компиляции, а не ввремя выполнения AFAIK).

Другие?

РЕДАКТИРОВАТЬ: причина, по которой я спрашиваю это (и, надеюсь, это сделает мой вопрос немного более обоснованным), потому что я работаю над небольшой библиотекойкоторый обеспечит функциональность этих инструкций.sizeof и cpblk уже реализованы - я хотел знать, что еще я мог пропустить, прежде чем двигаться дальше.

EDIT2: Используя ответ Эрика, я составил список инструкций:

  • Перерыв
  • Jmp
  • Калли
  • Cpobj
  • Ckfinite
  • Префикс [1-7]
  • Префиксref
  • Endfilter
  • Unaligned
  • Tailcall
  • Cpblk
  • Initblk

Был ряд других инструкцийкоторые не были включены в список, который я разделяю, потому что это в основном ярлыки для других инструкций (сжатых для экономии времени и пространства):

  • Ldarg [0-3]
  • Ldloc [0-3]
  • Stloc [0-3]
  • Ldc_ [I4_ [M1 / S / 0-8] / I8 / R4 / R8]
  • Ldind_ [I1 / U1 / I2 / U2 / I4 / U4 / I8 / R4 / R8]
  • Stind_ [I1 / I2 / I4 / I8 / R4 / R8]
  • Conv_ [I1/ I2 / I4 / I8 / R4 / R8 / U4 / U8 / U2 / U1]
  • Conv_Ovf_ [I1 / I2 / I4 / I8 / U1 / U2 / U4 / U8]
  • Conv_Ovf_[I1 / I2 / I4 / I8 / U1 / U2 / U4 / U8] _Un
  • Ldelem_ [I1 / I2 / I4 / I8 / U1 / U2 / U4 / R4 / R8]
  • Stelem_ [I1 / I2 / I4 / I8 / R4 / R8]

Ответы [ 4 ]

36 голосов
/ 18 августа 2011

Я имею в виду такие инструкции, как sizeof и cpblk - нет класса или команды, которая выполняет эти инструкции (sizeof в C # вычисляется во время компиляции, а не во время выполнения AFAIK).

Это неверно. Конечно, sizeof(int) будет считаться константой времени компиляции 4, но существует множество ситуаций (все в коде unsafe), когда компилятор полагается на среду выполнения, чтобы определить, какой объем памяти структуры. Рассмотрим, например, структуру, которая содержит два указателя. Это будет размер 8 на 32-битной машине, но 16 на 64-битной машине. В этих обстоятельствах компилятор сгенерирует размер кода операции.

Другие

У меня нет списка всех кодов операций, которые мы не производим - у меня никогда не было необходимости создавать такой список. Тем не менее, от всей души могу вам сказать, что в C # нет способа генерировать инструкцию call call (calli); нас иногда просят об этой функции, так как это улучшит производительность некоторых сценариев взаимодействия.

ОБНОВЛЕНИЕ: я просто скопировал исходный код, чтобы создать список кодов операций, которые мы определенно делаем производим. Это:

добавить
add_ovf
add_ovf_un
и
* список аргументов 1023 * 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
коробка
ш
br_s
brfalse
brfalse_s
brtrue
brtrue_s
звоните
callvirt
castclass
Ceq
ВКТ
cgt_un
сх
clt_un
ограничен
conv_i
conv_ovf_i
conv_ovf_i_un
conv_ovf_u
conv_ovf_u_un
conv_r
conv_r_un
conv_u
ДИВ
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_s
localloc
mkrefany
мул
mul_ovf
mul_ovf_un
отр
newarr
newobj
NOP
не
или
поп
* 1121 только для чтения * refanytype
refanyval
рем
rem_un
RET
Rethrow
З
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_ovf
sub_ovf_un
переключатель
бросить
unbox_any
летучий
xor

Я не собираюсь гарантировать, что это все из них, но это, безусловно, большинство из них. Затем вы можете сравнить это со списком всех кодов операций и посмотреть, чего не хватает.

13 голосов
/ 18 августа 2011

Основываясь на ответе Эрика, вот некоторые, которые я заметил. Где я вижу причину, я указал это, если не я свободно размышляю. Не стесняйтесь указывать, если эти предположения не верны.

Break

Сигнализирует об общей языковой инфраструктуре (CLI) для информирования отладчика о том, что остановлена ​​точка останова.

Вы могли бы сделать это, вызвав System.Diagnostics.Debugger.Break (), это, по-видимому, не использует эту инструкцию напрямую, а вместо этого использует метод BreakInternal (), встроенный в CLR.

Cpblk и Cpobj

Копирует указанное количество байтов из исходного адреса в адрес назначения. Копирует тип значения, расположенный по адресу объекта (тип &, * или native int), в адрес целевого объекта (type &, * или native int).

Я предполагаю, что они были добавлены для C ++ / CLI (ранее Managed C ++), но это чисто предположение с моей стороны. Они также могут присутствовать в определенных системных вызовах, но не генерируются обычно компилятором и предоставляют некоторую область для небезопасных развлечений и игр.

Endfilter

Передает управление из условия фильтра исключения обратно в обработчик исключений Common Language Infrastructure (CLI).

C # не поддерживает фильтрацию исключений. Компилятор VB, несомненно, использует это.

Initblk

Инициализирует указанный блок памяти по указанному адресу с заданным размером и начальным значением.

Я собираюсь снова предположить, что это потенциально полезно в небезопасном коде и C ++ / CLI

Jmp

Выход из текущего метода и переход к указанному методу.

Я предположу, что этот вид прыжков на батуте может быть полезен для тех, кто хочет избежать хвостовых вызовов. Возможно, DLR использует это?

Tailcall

Выполняет пост-фиксированную инструкцию вызова метода, так что кадр стека текущего метода удаляется перед выполнением фактической инструкции вызова.

Подробно обсуждено в другом месте, в настоящее время компилятор c # не генерирует этот код операции

Unaligned

Указывает, что адрес, находящийся в настоящее время на вершине стека оценки, может не совпадать с натуральным размером непосредственно следующей за ldind, stind, ldfld, stfld, ldobj, stobj, initblk или cpblk.

C # (и CLR) дает довольно много гарантий относительно согласованного характера большей части его результирующего кода и данных. Не удивительно, что это не испускается, но я понимаю, почему это будет включено.

Unbox

Преобразует в штучной упаковке представление типа значения в его распакованную форму.

Компилятор c # предпочитает использовать инструкцию Unbox_Any исключительно для этой цели. Я предполагаю, что, основываясь на добавлении этого к набору команд в выпуске 2.0, это делает генерики либо просто, либо намного проще. В тот момент использование его во всем коде для всего, обобщений или иным образом, было либо безопаснее, проще или быстрее (или некоторая комбинация всех).


Сноска:

Префикс1 , Префикс2, Префикс3, Префикс4, Префикс5, Префикс6, Префикс7, Префиксref

Инфраструктура. Это зарезервированная инструкция.

Это не инструкции как таковые. Некоторые инструкции IL длиннее других. Эти переменные длины должны начинаться с префиксов, которые сами по себе не являются действительными, чтобы сделать разбор понятным. Эти префиксные коды операций зарезервированы для этого, поэтому они не используются в других местах. Несомненно, кто-то, реализующий синтаксический анализатор на основе оператора switch для последовательности IL, оценит их, чтобы они могли перехватывать их и поддерживать состояние.

4 голосов
/ 18 августа 2011

Один интересный пример - tail.call ( OpCodes.Tailcall ), который делает возможной оптимизацию Tail Call для рекурсии.

1 голос
/ 18 августа 2011

Директива .override IL (я не знаю, правильный ли это термин, но это, конечно, не инструкция ), генерируется компилятором C #, но только в особый случай явной реализации интерфейса.

Было бы интересно иметь возможность использовать его более свободно, как в VB.NET, где члены реализации могут иметь псевдоним или даже иметь другой модификатор доступа , чем интерфейс член.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...