1 /* -----------------------------------------------------------------------------
2 * $Id: TailCalls.h,v 1.6 2000/11/07 10:42:56 simonmar Exp $
4 * (c) The GHC Team, 1998-1999
6 * Stuff for implementing proper tail jumps.
8 * ---------------------------------------------------------------------------*/
13 /* -----------------------------------------------------------------------------
14 Unmangled tail-jumping: use the mini interpretter.
15 -------------------------------------------------------------------------- */
17 #ifdef USE_MINIINTERPRETER
19 #define JMP_(cont) return(stgCast(StgFunPtr,cont))
25 /* -----------------------------------------------------------------------------
27 -------------------------------------------------------------------------- */
31 extern void __DISCARD__(void);
33 /* Note about discard: possibly there to fool GCC into clearing up
34 before we do the jump eg. if there are some arguments left on the C
35 stack that GCC hasn't popped yet. Also possibly to fool any
36 optimisations (a function call often acts as a barrier). Not sure
37 if any of this is necessary now -- SDM
39 Comment to above note: I don't think the __DISCARD__() in JMP_ is
40 necessary. Arguments should be popped from the C stack immediately
41 after returning from a function, as long as we pass -fno-defer-pop
42 to gcc. Moreover, a goto to a first-class label acts as a barrier
43 for optimisations in the same way a function call does.
47 /* The goto here seems to cause gcc -O2 to delete all the code after
48 it - including the FE_ marker and the epilogue code - exactly what
56 target = (void *)(cont); \
60 #endif /* i386_TARGET_ARCH */
62 /* -----------------------------------------------------------------------------
64 -------------------------------------------------------------------------- */
66 #ifdef sparc_TARGET_ARCH
68 #define JMP_(cont) ((F_) (cont))()
69 /* Oh so happily, the above turns into a "call" instruction,
70 which, on a SPARC, is nothing but a "jmpl" with the
71 return address in %o7 [which we don't care about].
74 /* Don't need these for sparc mangling */
78 #endif /* sparc_TARGET_ARCH */
80 /* -----------------------------------------------------------------------------
82 -------------------------------------------------------------------------- */
84 #ifdef alpha_TARGET_ARCH
86 register void *_procedure __asm__("$27");
89 do { _procedure = (void *)(cont); \
93 /* Don't need these for alpha mangling */
97 #endif /* alpha_TARGET_ARCH */
99 /* -----------------------------------------------------------------------------
101 -------------------------------------------------------------------------- */
103 #ifdef hppa1_1_hp_hpux_TARGET
106 do { void *_procedure = (void *)(cont); \
110 #endif /* hppa1_1_hp_hpux_TARGET */
112 /* -----------------------------------------------------------------------------
115 These are markers indicating the start and end of Real Code in a
116 function. All instructions between the actual start and end of the
117 function and these markers is shredded by the mangler.
118 -------------------------------------------------------------------------- */
120 /* The following __DISCARD__() has become necessary with gcc 2.96 on x86.
121 * It prevents gcc from moving stack manipulation code from the function
122 * body (aka the Real Code) into the function prologue, ie, from moving it
123 * over the --- BEGIN --- marker. It should be noted that (like some
124 * other black magic in GHC's code), there is no essential reason why gcc
125 * could not move some stack manipulation code across the __DISCARD__() -
126 * it just doesn't choose to do it at the moment.
130 #define FB_ __asm__ volatile ("--- BEGIN ---"); __DISCARD__ ();
134 #define FE_ __asm__ volatile ("--- END ---");
137 #endif /* !USE_MINIINTERPRETER */
139 #endif /* TAILCALLS_H */