Next: Library Calls, Previous: Varargs, Up: Target Macros
一个蹦床trampoline为在运行时,当使用嵌套函数的地址时,创建的一小块代码。其通常驻于栈上,在包含函数的栈帧中。这些宏告诉GCC如何生成代码来分配和初始化一个蹦床。
在蹦床中的指令必须做两件事情:将一个常量地址加载到静态链寄存器中,并跳转到嵌套函数的实际地址。在CISC机器,像m68k上,这要求两条指令,一个move立即数和一个jump。然后两个地址存放在蹦床中作为字长的立即操作数。在RISC机器上,其通常需要分成两部分加载每个地址到寄存器中。然后地址的各部分形成独立的立即操作数。
用来初始化蹦床的代码必须将变量的组成部分——静态链值和函数地址——存储到指令的立即操作数中。在CISC机器上,这是简单的复制每个地址到一个内存引用,在蹦床起始处的合适偏移量上。在RISC机器上,其可能需要拿出部分地址并单独存储它们。
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.
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 byassemble_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 allTRAMPOLINE_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.
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.
在许多机器上实现蹦床是困难的,因为它们具有独立的指令和数据缓存。 写到栈位置中使得无法清除指令缓存中的内存,所以当程序跳转到那个位置时, 其执行了旧的内容。
有两种可能的解决方法。一种是清除指令缓存的相关部分,当蹦床被建立的时候。 另一种是使所有蹦床为等同的,通过使它们跳转到一个标准的子程序中。 前者使得蹦床执行更快;后者使得初始化更快。
要在初始化蹦床时清除指令缓存,定义下列宏。
如果被定义,将扩展为一个C表达式,在指定的间隔处来清除指令缓存。 该宏的定义通常为一系列
asm
语句。beg和end都为指针表达式。
操作系统可能还需要栈被设为可执行的,在调用蹦床之前。要实现这种需求,定义下列宏。
定义该宏,如果在执行位于栈上的代码之前必须执行特定的操作。 宏应该扩展为一系列的C文件作用域的结构(例如函数)并提供一个唯一的如何口点名 为
__enable_execute_stack
。target负责生成对入口点的调用, 例如从INITIALIZE_TRAMPOLINE
宏中。
要使用标准的子程序,定义下列宏。另外, 你必须确信在蹦床中的指令使用相同的指令来填充整个缓存行, 或者蹦床代码的起始处总是在缓存行的某点被对齐。查看m68k.h作为参考。