Trampolines - GNU Compiler Collection (GCC) Internals
Description: GNU Compiler Collection (GCC) Internals

Next: Library Calls, Previous: Varargs, Up: Target Macros

### 17.12 Trampolines for Nested Functions

A trampoline is a small piece of code that is created at run time when the address of a nested function is taken. It normally resides on the stack, in the stack frame of the containing function. These macros tell GCC how to generate code to allocate and initialize a trampoline.

The instructions in the trampoline must do two things: load a constant address into the static chain register, and jump to the real address of the nested function. On CISC machines such as the m68k, this requires two instructions, a move immediate and a jump. Then the two addresses exist in the trampoline as word-long immediate operands. On RISC machines, it is often necessary to load each address into a register in two parts. Then pieces of each address form separate immediate operands.

The code generated to initialize the trampoline must store the variable parts—the static chain value and the function address—into the immediate operands of the instructions. On a CISC machine, this is simply a matter of copying each address to a memory reference at the proper offset from the start of the trampoline. On a RISC machine, it may be necessary to take out pieces of the address and store them separately.

— 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

> Return the section into which the trampoline template is to be placed (see Sections). The default value is `readonly_data_section`.

— Macro: TRAMPOLINE_SIZE

> A C expression for the size in bytes of the trampoline, as an integer.

— Macro: TRAMPOLINE_ALIGNMENT

> Alignment required for trampolines, in bits.

> If you don't define this macro, the value of `FUNCTION_ALIGNMENT` is used for aligning trampolines.

— 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.

Implementing trampolines is difficult on many machines because they have separate instruction and data caches. Writing into a stack location fails to clear the memory in the instruction cache, so when the program jumps to that location, it executes the old contents.

Here are two possible solutions. One is to clear the relevant parts of the instruction cache whenever a trampoline is set up. The other is to make all trampolines identical, by having them jump to a standard subroutine. The former technique makes trampoline execution faster; the latter makes initialization faster.

To clear the instruction cache when a trampoline is initialized, define the following macro.

— Macro: CLEAR_INSN_CACHE (beg, end)

> If defined, expands to a C expression clearing the instruction cache in the specified interval. The definition of this macro would typically be a series of `asm` statements. Both beg and end are both pointer expressions.

The operating system may also require the stack to be made executable before calling the trampoline. To implement this requirement, define the following macro.

— Macro: ENABLE_EXECUTE_STACK

> Define this macro if certain operations must be performed before executing code located on the stack. The macro should expand to a series of C file-scope constructs (e.g. functions) and provide a unique entry point named `__enable_execute_stack`. The target is responsible for emitting calls to the entry point in the code, for example from the `TARGET_TRAMPOLINE_INIT` hook.

To use a standard subroutine, define the following macro. In addition, you must make sure that the instructions in a trampoline fill an entire cache line with identical instructions, or else ensure that the beginning of the trampoline code is always aligned at the same point in its cache line. Look in `m68k.h` as a guide.

— Macro: TRANSFER_FROM_TRAMPOLINE

> Define this macro if trampolines need a special subroutine to do their work. The macro should expand to a series of `asm` statements which will be compiled with GCC. They go in a library function named `__transfer_from_trampoline`.

> If you need to avoid executing the ordinary prologue code of a compiled C function when you jump to the subroutine, you can do so by placing a special label of your own in the assembler code. Use one `asm` statement to generate an assembler label, and another to make the label global. Then trampolines can use that label to jump directly to your special assembler code.