Соглашение о вызовах OCaml :является ли это точной сводкой?

никогда ничего не было записано. Я пытался найти соглашение о вызовах OCaml, чтобы я мог вручную интерпретировать трассировки стека, которые gdb не может проанализировать. К сожалению, кажется, что ничего никогда не было записано на английском языке, кроме общих замечаний. Например, в блогах люди будут комментировать, что OCaml передает много аргументов в регистры. (Если где-то есть документация на английском языке, буду признательна за ссылку.)

Итак, я пытался разгадать это из источника окамлопта.Кто-нибудь может подтвердить правильность этих догадок?

И, если я прав насчет того, что первые десять аргументов передаются в регистры, неужели вообще невозможно восстановить аргументы для вызова функции? В C аргументы все равно будут помещаться куда-нибудь в стек, если только я вернусь к нужному фрейму. В OCaml кажется, что вызываемые объекты могут уничтожать аргументы своих вызывающих объектов.


Распределение регистров(из/asmcomp/amd64/proc.ml)

Для вызова функций OCaml

  • Первые 10 целочисленных аргументов и аргументов-указателей передаются в регистры rax, rbx, rdi, rsi, rdx, rcx, r8, r9, r10 и r11
  • . Первые 10 аргументов с плавающей запятой -передаются в регистрах xmm0 -xmm9
  • Дополнительные аргументы помещаются в стек (. самый левый -первый -в?), числа с плавающей запятой, целые числа и указатели смешаны
  • Указатель ловушки (см. Исключения ниже )передается в r14
  • Указатель выделения (предположительно для вспомогательной кучи, как описано в этом сообщении в блоге ). пройдено в r15
  • Возвращаемое значение возвращается в формате rax, если оно является целым числом или указателем, и в формате xmm0, если оно представляет собой число с плавающей запятой
  • . Все регистры сохраняются вызывающим -?

Для вызова функций C используется стандартное соглашение amd64 C :

  • . Первые шесть целочисленных аргументов и аргументов указателя передаются в rdi, rsi, rdx, rcs, r8 и r9
  • . Первые восемь аргументов с плавающей запятой передаются в xmm0 -xmm7
  • Дополнительные аргументы помещаются в стек
  • . Возвращаемое значение передается обратно в формате rax или xmm0
  • . Регистры rbx, rbp и r12 -r15 вызываются -и сохраняются

. Обратный адрес(из/asmcomp/amd64/emit.mlp)

Адрес возврата — это первый указатель, помещаемый в кадр вызова, в соответствии с соглашением amd64 C. (Я предполагаю, что инструкция retпредполагает такую ​​компоновку.)

Исключения(из/asmcomp/linearize.ml)

Код try (...body...) with (...handler...); (...rest...)линеаризуется следующим образом:

Lsetuptrap.body
(...handler...)
Lbranch.join
Llabel.body
Lpushtrap
(...body...)
Lpoptrap
Llabel.join
(...rest...)

а затем выпускается в виде сборки, подобной этой (места назначения справа):

call.body
(...handler...)
jmp.join
.body:
pushq %r14
movq %rsp, %r14
(...body...)
popq %r14
addq %rsp, 8
.join:
(...rest...)

Где-то в теле есть линеаризованный код операции Lraise, который генерируется как эта точная сборка :

movq %r14, %rsp
popq %r14
ret

. Что действительно аккуратно! Вместо этого setjmp/longjmp мы создаем фиктивный фрейм, адрес возврата которого является обработчиком исключений, и единственным локальным адресом которого является предыдущий такой фиктивный фрейм. В /asmcomp/amd64/proc.mlесть комментарий, в котором $r14 называется «указатель ловушки», поэтому я буду называть этот фиктивный кадр кадром-ловушкой. Когда мы хотим вызвать исключение, мы устанавливаем указатель стека на самый последний кадр ловушки, устанавливаем указатель ловушки на кадр ловушки перед ним, а затем «возвращаемся» в обработчик исключений. Бьюсь об заклад, если обработчик исключений не сможет обработать это исключение, он просто вызовет его повторно.

Исключение составляет %eax.

20
задан Wang 4 July 2012 в 03:46
поделиться