Next: , Previous: Varargs, Up: Target Macros


17.12 嵌套函数的蹦床

一个蹦床trampoline为在运行时,当使用嵌套函数的地址时,创建的一小块代码。其通常驻于栈上,在包含函数的栈帧中。这些宏告诉GCC如何生成代码来分配和初始化一个蹦床。

在蹦床中的指令必须做两件事情:将一个常量地址加载到静态链寄存器中,并跳转到嵌套函数的实际地址。在CISC机器,像m68k上,这要求两条指令,一个move立即数和一个jump。然后两个地址存放在蹦床中作为字长的立即操作数。在RISC机器上,其通常需要分成两部分加载每个地址到寄存器中。然后地址的各部分形成独立的立即操作数。

用来初始化蹦床的代码必须将变量的组成部分——静态链值和函数地址——存储到指令的立即操作数中。在CISC机器上,这是简单的复制每个地址到一个内存引用,在蹦床起始处的合适偏移量上。在RISC机器上,其可能需要拿出部分地址并单独存储它们。

— Target Hook: void TARGET_ASM_TRAMPOLINE_TEMPLATE (FILE *f)

This hook is called by assemble_trampoline_template to output, on the stream f, assembler code for a block of data that contains the constant parts of a trampoline. This code should not include a label—the label is taken care of automatically.

If you do not define this hook, it means no template is needed for the target. Do not define this hook on systems where the block move code to copy the trampoline into place would be larger than the code to generate it on the spot.

— Macro: TRAMPOLINE_SECTION

返回蹦床模版被放入的section(参见Sections)。 缺省值为readonly_data_section

— Macro: TRAMPOLINE_SIZE

一个C表达式,蹦床的字节单位的大小,为整数。

— Macro: TRAMPOLINE_ALIGNMENT

蹦床需要的对齐,以位为单位。

如果没有定义该宏,则使用BIGGEST_ALIGNMENT的值来对齐蹦床。

— Target Hook: void TARGET_TRAMPOLINE_INIT (rtx m_tramp, tree fndecl, rtx static_chain)

This hook is called to initialize a trampoline. m_tramp is an RTX for the memory block for the trampoline; fndecl is the FUNCTION_DECL for the nested function; static_chain is an RTX for the static chain value that should be passed to the function when it is called.

If the target defines TARGET_ASM_TRAMPOLINE_TEMPLATE, then the first thing this hook should do is emit a block move into m_tramp from the memory block returned by assemble_trampoline_template. Note that the block move need only cover the constant parts of the trampoline. If the target isolates the variable parts of the trampoline to the end, not all TRAMPOLINE_SIZE bytes need be copied.

If the target requires any other actions, such as flushing caches or enabling stack execution, these actions should be performed after initializing the trampoline proper.

— Target Hook: rtx TARGET_TRAMPOLINE_ADJUST_ADDRESS (rtx addr)

This hook should perform any machine-specific adjustment in the address of the trampoline. Its argument contains the address of the memory block that was passed to TARGET_TRAMPOLINE_INIT. In case the address to be used for a function call should be different from the address at which the template was stored, the different address should be returned; otherwise addr should be returned unchanged. If this hook is not defined, addr will be used for function calls.

在许多机器上实现蹦床是困难的,因为它们具有独立的指令和数据缓存。 写到栈位置中使得无法清除指令缓存中的内存,所以当程序跳转到那个位置时, 其执行了旧的内容。

有两种可能的解决方法。一种是清除指令缓存的相关部分,当蹦床被建立的时候。 另一种是使所有蹦床为等同的,通过使它们跳转到一个标准的子程序中。 前者使得蹦床执行更快;后者使得初始化更快。

要在初始化蹦床时清除指令缓存,定义下列宏。

— Macro: CLEAR_INSN_CACHE (beg, end)

如果被定义,将扩展为一个C表达式,在指定的间隔处来清除指令缓存。 该宏的定义通常为一系列asm语句。begend都为指针表达式。

操作系统可能还需要栈被设为可执行的,在调用蹦床之前。要实现这种需求,定义下列宏。

— Macro: ENABLE_EXECUTE_STACK

定义该宏,如果在执行位于栈上的代码之前必须执行特定的操作。 宏应该扩展为一系列的C文件作用域的结构(例如函数)并提供一个唯一的如何口点名 为__enable_execute_stack。target负责生成对入口点的调用, 例如从INITIALIZE_TRAMPOLINE宏中。

要使用标准的子程序,定义下列宏。另外, 你必须确信在蹦床中的指令使用相同的指令来填充整个缓存行, 或者蹦床代码的起始处总是在缓存行的某点被对齐。查看m68k.h作为参考。

— Macro: TRANSFER_FROM_TRAMPOLINE

定义该宏,如果蹦床需要一个特定的子程序来做它们的工作。 该宏应该扩展为一系列的asm语句,其将由GCC来编译。 它们放在名为__transfer_from_trampoline的库函数中。

如果当你跳转到子程序时,你需要避免普通的被编译的C函数的序言代码, 你可以通过在汇编代码中放一个你自己的特定标号。 使用一条asm语句来生成汇编标号,另一条语句使得标号为global的。 然后蹦床可以使用该标号直接跳到你特定的汇编代码上。