gpt4 book ai didi

ocaml - OCaml调用约定:这是准确的摘要吗?

转载 作者:行者123 更新时间:2023-12-03 12:17:54 24 4
gpt4 key购买 nike

我一直在尝试找到OCaml调用约定,以便可以手动解释gdb无法解析的堆栈跟踪。不幸的是,除了一般性的观察,似乎没有什么用英语写下来。例如,人们会在OCaml在寄存器中传递许多参数的博客上发表评论。 (如果某处有英文文档,则非常感谢您提供链接。)

因此,我一直在尝试从ocamlopt来源中解惑。谁能证实这些猜测的准确性?

并且,如果我对在寄存器中传递的前十个参数是正确的,是否通常无法将这些参数恢复到函数调用中?在C语言中,如果仅返回到正确的帧,则参数仍将被 push 堆栈中的某个位置。在OCaml中,被调用者似乎可以随意销毁其调用者的论点。

寄存器分配(来自/asmcomp/amd64/proc.ml)

要调用OCaml函数,

  • 前10个整数和指针参数在寄存器rax,rbx,rdi,rsi,rdx,rcx,r8,r9,r10和r11中传递
  • 前10个浮点参数在寄存器xmm0-xmm9中传递
  • 附加参数被压入堆栈( leftmost-first-in?),浮点数和整数以及指针混合
  • 陷阱指针(请参见下面的异常)在r14中传递
  • 分配指针(大概是针对此blog post中所述的次要堆)在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约定,返回地址是 push 调用帧的第一个指针。 (我猜 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...)

    在 body 的某个位置,有一个线性化的操作码 Lraise,它作为这个确切的程序集发出:
    movq %r14, %rsp
    popq %r14
    ret

    真的很整洁!代替此setjmp / longjmp业务,我们创建一个虚拟框架,其返回地址是异常处理程序,并且其唯一的本地地址是先前的此类虚拟框架。 /asmcomp/amd64/proc.ml有一个注释,将$ r14称为“陷阱指针”,因此我将此虚拟框架称为陷阱框架。当我们想引发异常时,我们将堆栈指针设置为最新的陷阱帧,将陷阱指针设置为之前的陷阱帧,然后“返回”到异常处理程序中。我敢打赌,如果异常处理程序无法处理此异常,它将重新引发它。

    %eax异常(exception)。

    最佳答案

    这比问题更答案!我对主题的了解是一样的,就像您一样,我是通过查看源中学到的,因此不要指望进一步的精确性比您的文章更具权威性。

    是的,我认为OCaml仅将专门的调用约定与调用者保存寄存器一起使用。这种选择的好处是它简化了尾部调用:当您跳过尾部调用¹时,不必溢出或重新加载任何寄存器。

    ¹:对于非自已的尾部 call ,这仅在没有太多参数的情况下有效,因此我们不需要溢出。如果需要堆栈分配,则该调用将变为非尾调用。

    请注意,调用约定仍然强烈取决于目标体系结构。例如,在x86上,当寄存器用完时且在溢出到堆栈之前,会使用少量的全局变量来保留尾部调用。

    我也同意“leftmost-first-in”:参数由calling_conventions中的proc.ml遍历,由slot_offset中的emit.mlp偏移量存储;它们是从右到左计算的,但是按顺序返回,格式为selectgen.ml

    关于ocaml - OCaml调用约定:这是准确的摘要吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11322163/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com