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 GNU CC 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.
TRAMPOLINE_TEMPLATE (file)
TRAMPOLINE_SECTION
TRAMPOLINE_SIZE
TRAMPOLINE_ALIGNMENT
If you don't define this macro, the value of BIGGEST_ALIGNMENT
is used for aligning trampolines.
INITIALIZE_TRAMPOLINE (addr, fnaddr, static_chain)
ALLOCATE_TRAMPOLINE (fp)
If this macro is not defined, by default the trampoline is allocated as a stack slot. This default is right for most machines. The exceptions are machines where it is impossible to execute instructions in the stack area. On such machines, you may have to implement a separate stack, using this macro in conjunction with FUNCTION_PROLOGUE
and FUNCTION_EPILOGUE
.
fp points to a data structure, a struct function
, which describes the compilation status of the immediate containing function of the function which the trampoline is for. Normally (when ALLOCATE_TRAMPOLINE
is not defined), the stack slot for the trampoline is in the stack frame of this containing function. Other allocation strategies probably must do something analogous with this information.
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 macros which describe the shape of the cache.
INSN_CACHE_SIZE
INSN_CACHE_LINE_WIDTH
INSN_CACHE_DEPTH
Alternatively, if the machine has system calls or instructions to clear the instruction cache directly, you can define the following macro.
CLEAR_INSN_CACHE (BEG, END)
asm
statements. Both BEG and END are both pointer expressions. 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.
TRANSFER_FROM_TRAMPOLINE
asm
statements which will be compiled with GNU CC. 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.