Next: , Up: Stack and Calling


17.10.1 基本的帧布局

这里是基本的栈布局。

— Macro: STACK_GROWS_DOWNWARD

定义该宏,如果将一个字压入栈中使得栈指针移向更小的地址。

当我们说“定义该宏,如果...”,这意味着编译器只是使用#ifdef来检查该宏, 所以具体定义的值并没有关系。

— Macro: STACK_PUSH_CODE

该宏定义了当压栈所使用的操作。对于RTL形式, 压栈操作将为(set (mem (STACK_PUSH_CODE (reg sp))) ...)

可选择的方式为PRE_DEC, POST_DEC, PRE_INCPOST_INC。 使用哪一个是正确的,取决于栈的方向和栈指针是否指向栈中的最后一项, 还是指向之后的空间。

缺省为PRE_DEC,当STACK_GROWS_DOWNWARD被定义时, 这大多情况下都是正确,否则为PRE_INC,这经常是错误的。

— Macro: FRAME_GROWS_DOWNWARD

定义该宏为非零值,如果局部变量槽的地址位于帧指针的负偏移处。

— Macro: ARGS_GROW_DOWNWARD

定义该宏,如果函数的连续的参数在栈上的地址是递减的。

— Macro: STARTING_FRAME_OFFSET

帧指针到第一个被分配的局部变量槽的偏移量。

如果FRAME_GROWS_DOWNWARD,则通过从STARTING_FRAME_OFFSET减去第一个 栈槽的长度来查找下一个栈槽的偏移量。否则,通过从STARTING_FRAME_OFFSET 加上第一个栈槽的长度来查找。

— Macro: STACK_ALIGNMENT_NEEDED

定义为0,来禁止在重载过程中对栈进行最后的对齐操作。缺省的非0值适合于大多port。

在一些port上,STARTING_FRAME_OFFSET为非0, 或者在局部块之后有一块寄存器保存区域,其不需要对齐到STACK_BOUNDARY, 这样禁止栈对齐并且在后端实现可能会更好。

— Macro: STACK_POINTER_OFFSET

从栈指针寄存器到第一个输出的参数所放在的位置的偏移量。 如果没有指定,则缺省值0被使用。这对于大多数机器都合适。

如果ARGS_GROW_DOWNWARD, 则这是输出参数位于的第一个位置的上面的位置的偏移量。

— Macro: FIRST_PARM_OFFSET (fundecl)

参数指针寄存器到第一个参数的地址的偏移量。在一些机器上, 其可能依赖于函数的数据类型。

如果ARGS_GROW_DOWNWARD,则这是第一个参数的地址的上面的位置的偏移量。

— Macro: STACK_DYNAMIC_OFFSET (fundecl)

栈指针寄存器到在栈上动态分配的对象的偏移量,例如,通过alloca

该宏的缺省值为STACK_POINTER_OFFSET加上输出参数的长度。 缺省值对于大多数机器是正确的。详情参见function.c

— Macro: INITIAL_FRAME_ADDRESS_RTX

一个C表达式,其值为RTL,表示初始栈帧的地址。 该地址被传给RETURN_ADDR_RTXDYNAMIC_CHAIN_ADDRESS。 如果你没有定义该宏,则一个合理的缺省值将被使用。定义该宏, 可以使帧指针消除在__builtin_frame_address (count)__builtin_return_address (count)不等于0的情况下工作。

— Macro: DYNAMIC_CHAIN_ADDRESS (frameaddr)

一个C表达式,其值为RTL,表示栈帧中的地址,指向被存储的调用者的帧。 假设frameaddr为一个栈帧本身的地址的RTL表达式。

如果你没有定义该宏,则缺省为返回frameaddr的值——也就是说, 栈帧地址也是指向之前帧的地址。

— Macro: SETUP_FRAME_ADDRESSES

如果定义,为一个C表达式,其产生机器特定的代码来建立栈,使得可以访问任意的帧。 例如,在SPARC上,我们必须刷新栈的所有寄存器窗口,在我们可以访问任意栈帧之前。 你很少会需要定义该宏。

— Target Hook: bool TARGET_BUILTIN_SETJMP_FRAME_VALUE ()

该target钩子应该返回一个rtx,用于将当前帧的地址存储到内建的setjmp缓存中。 缺省值,virtual_stack_vars_rtx,对于大多数机器是正确的。 一种你可能需要定义该target钩子的原因是, 如果hard_frame_pointer_rtx在你的机器上是合适的值。

— Macro: FRAME_ADDR_RTX (frameaddr)

一个C表达式,其值为RTL,表示当前帧的帧地址。frameaddr为当前帧的帧指针。 这用于__builtin_frame_address。你只有当帧地址与帧指针不同的时候才需要定义该宏。 大多数机器不需要定义该宏。

— Macro: RETURN_ADDR_RTX (count, frameaddr)

A C expression whose value is RTL representing the value of the return address for the frame count steps up from the current frame, after the prologue. frameaddr is the frame pointer of the count frame, or the frame pointer of the count − 1 frame if RETURN_ADDR_IN_PREVIOUS_FRAME is defined.

The value of the expression must always be the correct address when count is zero, but may be NULL_RTX if there is no way to determine the return address of other frames.

— Macro: RETURN_ADDR_IN_PREVIOUS_FRAME

定义该宏,如果一个特定的栈帧的返回地址是从之前栈帧的帧指针中访问的。

— Macro: INCOMING_RETURN_ADDR_RTX

一个C表达式,其值为RTL,表示在任何函数的起始处,在序言之前, 流入的返回地址的位置。该RTL或者为一个REG, 指示返回地址保存在‘REG’中,或者一个MEM表示位于栈中。

你只在你想支持调用帧调试信息,像DWARF2提供的那样,的时候才需要定义该宏。

如果该RTL为一个REG, 你还要定义DWARF_FRAME_RETURN_COLUMNDWARF_FRAME_REGNUM (REGNO)

— Macro: DWARF_ALT_FRAME_RETURN_COLUMN

一个C表达式,其值为一个整数,给出了DWARF2的列号,可以用作替代的返回列。 column必须不对应于任何gcc硬件寄存器(也就是说, 其必须不在DWARF_FRAME_REGNUM的范围中)。

该宏当被设为一个通用寄存器,但是候选的column需要用于signal帧的时候会很有用。 一些target还使用了不同的帧返回列。

— Macro: DWARF_ZERO_REG

一个C表达式,其值为一个整数,给出了DWARF2寄存器编号,其被认为总是具有值0。 这应该只当target的体系结构中具有一个0寄存器并且认为使用寄存器编号来确定栈的 回溯是一个好主意的时候才被定义。新的part应该避免该宏。

— Target Hook: void TARGET_DWARF_HANDLE_FRAME_UNSPEC (const char *label, rtx pattern, int index)

该target钩子允许后端生成帧相关的insn,其包含了UNSPECs或UNSPEC_VOLATILEs。 DWARF2调用帧调试信息引擎将会按照如下的形式来调用它

          (set (reg) (unspec [...] UNSPEC_INDEX))

          (set (reg) (unspec_volatile [...] UNSPECV_INDEX)).

来使后端生成调用帧指令。label为insn附带的CFI标号, pattern为insn的指令模式, indexUNSPEC_INDEXUNSPECV_INDEX

— Macro: INCOMING_FRAME_SP_OFFSET

一个C表达式,其值为一个整数,给出了偏移字节数, 从栈指针寄存器到任何函数的起始处,序言之前的栈帧的顶部。 帧的顶部被定义为之前帧的栈指针的值,就在call指令之前。

你只有当你想支持像DWARF2提供的那样的帧调试信息时才需要定义该宏。

— Macro: ARG_POINTER_CFA_OFFSET (fundecl)

一个C表达式,其值为一个整数,给出了偏移字节数,从参数指针到规范化帧地址(cfa)。 最终的值应该与通过INCOMING_FRAME_SP_OFFSET所计算的一致。 不幸的是这在虚寄存器实例化的时候不可用。

该宏的缺省值为FIRST_PARM_OFFSET (fundecl),其对于大多数机器是正确的; 总的来说,参数在栈帧之前被找到。注意有些情况不是这样的,一些target将寄存器保存在调用者的帧中,像SPARC和rs6000,这样的target就不需要定义该宏。

你只有当缺省是不正确的时候, 以及你想支持像DWARF2提供的那样的帧调试信息时才需要定义该宏。

— Macro: FRAME_POINTER_CFA_OFFSET (fundecl)

如果被定义,则为一个C表达式,其值为一个整数,给出了偏移字节数, 从帧指针到规范化帧地址(cfa)。 最终的值应该与通过INCOMING_FRAME_SP_OFFSET所计算的一致。

通常CFA被作为参数指针的偏移量来计算,通过ARG_POINTER_CFA_OFFSET, 但是如果参数指针是一个变量,这就不太可能了。如果该宏被定义, 它暗示了虚寄存器实例化应该基于帧指针而不是参数指针。 FRAME_POINTER_CFA_OFFSETARG_POINTER_CFA_OFFSET只有一个应该被定义。

— Macro: CFA_FRAME_BASE_OFFSET (fundecl)

如果定义,则为一个C表达式,其值为一个整数,给出了偏移字节数, 从规范化帧地址(cfa)到DWARF2调试信息使用的frame base。缺省为0。 不同的值可以在一些port上减少调试信息的大小。