调用堆栈管理

时间:2013-03-16 11:40:42

标签: haskell compilation callstack

这根本不是Haskell的问题,但我想有很多人会跟着Haskell标签知道这个问题的答案......

我正在尝试围绕如何保存函数的输入输出局部变量临时值在同一个堆栈上,但在退出时最终得到正确的堆栈布局。

通常,堆栈提供推送和拉取操作,这些操作仅修改最顶层的堆栈项。有时您还可以随意读取堆栈中的项目。 (这解释了如何将变量保存在那里并随机访问它们。)但通常改变堆栈大小的唯一方法是将项目拉出来。如果您想将项目保留在堆栈顶部并删除其下方的内容,那就不太好了。

真正的编译器如何做这些事情?

2 个答案:

答案 0 :(得分:2)

调用堆栈 frame 可以在参数所在的空间之前为返回值保留空间,然后是本地。这就是为什么知道类型有助于决定保留空间的大小。或者,在像Lisp这样的动态语言中,指向盒装值的指针会在那里。它只是特定函数调用协议的一部分。

带有闭包的语言中的运行时堆栈通常是一棵树(参见“Funarg问题”)。

答案 1 :(得分:2)

我不能直接与Haskell对话,但一般来说,应用程序二进制接口(或ABI)的工作是指定数据如何传递到函数和从函数传递(称为调用约定)。根据调用约定和数据大小,您提及的部分或全部内容可能存储在寄存器(甚至是全局)中而不是堆栈中。此外,调用函数的返回地址和可能的某些处理器状态也将存储在堆栈中。

OS X IA-32 Function Calling Conventions为例。堆栈布局:

OS X IA-32 stack convention

在此调用约定中,返回值通常存储在寄存器