OCaml调用约定:这是一个准确的总结吗?
我一直在尝试找到OCaml调用约定,以便手动解释gdb无法解析的堆栈跟踪。不幸的是,除了一般的观察之外,似乎没有任何东西用英语写下来。例如,人们会在博客上评论OCaml在寄存器中传递了许多参数。(如果某处有英文文档,请提供链接。) 所以我一直在试图从ocamlopt的来源中找出答案。有人能证实这些猜测的准确性吗 如果我在寄存器中传递的前十个参数是正确的,那么通常不可能将这些参数恢复到函数调用中吗?在C语言中,只要我返回到正确的帧,参数仍然会被推到堆栈的某个地方。在OCaml中,似乎被调用方可以自由地销毁调用方的参数OCaml调用约定:这是一个准确的总结吗?,ocaml,Ocaml,我一直在尝试找到OCaml调用约定,以便手动解释gdb无法解析的堆栈跟踪。不幸的是,除了一般的观察之外,似乎没有任何东西用英语写下来。例如,人们会在博客上评论OCaml在寄存器中传递了许多参数。(如果某处有英文文档,请提供链接。) 所以我一直在试图从ocamlopt的来源中找出答案。有人能证实这些猜测的准确性吗 如果我在寄存器中传递的前十个参数是正确的,那么通常不可能将这些参数恢复到函数调用中吗?在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
- 所有寄存器都已保存?
- 前六个整数和指针参数在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…)和(…handler…);(…rest…
线性化如下:
Lsetuptrap .body
(...handler...)
Lbranch .join
Llabel .body
Lpushtrap
(...body...)
Lpoptrap
Llabel .join
(...rest...)
然后像这样作为程序集发出(右侧的目的地):
在身体的某个地方,有一个线性化的操作码Lraise
,它作为这个精确的组件发出:
movq %r14, %rsp
popq %r14
ret
真是太好了!我们不创建setjmp/longjmp业务,而是创建一个虚拟帧,其返回地址是异常处理程序,其唯一本地地址是前一个此类虚拟帧。/asmcomp/amd64/proc.ml
有一条注释,将$r14称为“陷阱指针”,因此我将此虚拟帧称为陷阱帧。当我们想要引发异常时,我们将堆栈指针设置为最近的陷阱帧,将陷阱指针设置为之前的陷阱帧,然后“返回”到异常处理程序中。我打赌如果异常处理程序不能处理这个异常,它只会重新运行它
例外情况出现在%eax中。这与其说是一个问题,不如说是一个答案!关于这个话题,我知道的一点是,我通过查看源代码学到的,就像你一样,所以不要期望进一步的精确性会比你的文章更权威 是的,我认为OCaml只对调用方保存寄存器使用专门的调用约定。这种选择的一个好处是它简化了尾部调用:当您跳过尾部调用时,您不必溢出或重新加载任何寄存器 1:对于非自尾调用,这只在没有太多参数的情况下有效,因此我们不需要溢出。如果需要堆栈分配,则该调用将转换为非尾部调用 请注意,调用约定仍然强烈依赖于目标体系结构。例如,在x86上,当寄存器耗尽时,在堆栈溢出之前,使用少量全局变量来保留尾部调用
我还同意“最左边的第一位”:参数按顺序通过调用
proc.ml
中的约定进行遍历,并按偏移顺序存储在emit.mlp中的slot\u offset
中;它们从右到左计算,但按顺序返回,在selectgen.ml
是中,您无法从调用中恢复参数,因为OCaml尝试尽可能地重用寄存器,因此如果在函数的剩余部分不再有用,将销毁其内容。调试器无法打印参数,只能在函数中的给定点打印仍然有效的变量,但为此,需要修改ocamlopt以转储DWARF代码以恢复值
movq %r14, %rsp
popq %r14
ret