[project @ 2005-03-08 08:59:58 by simonmar]
[ghc-hetmet.git] / ghc / includes / TailCalls.h
1 /* -----------------------------------------------------------------------------
2  * $Id: TailCalls.h,v 1.19 2005/03/08 08:59:58 simonmar Exp $
3  *
4  * (c) The GHC Team, 1998-1999
5  *
6  * Stuff for implementing proper tail jumps.
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #ifndef TAILCALLS_H
11 #define TAILCALLS_H
12
13 /* -----------------------------------------------------------------------------
14    Unmangled tail-jumping: use the mini interpretter.
15    -------------------------------------------------------------------------- */
16
17 #ifdef USE_MINIINTERPRETER
18
19 #define JMP_(cont) return((StgFunPtr)(cont))
20 #define FB_
21 #define FE_
22
23 #else
24
25 extern void __DISCARD__(void);
26
27 /* -----------------------------------------------------------------------------
28    Tail calling on x86
29    -------------------------------------------------------------------------- */
30
31 #if i386_HOST_ARCH
32
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
38
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. 
44    -= chak
45    */
46
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
49    we want! -- SDM
50    */
51
52 #define JMP_(cont)                      \
53     {                                   \
54       void *__target;                   \
55       __DISCARD__();                    \
56       __target = (void *)(cont);        \
57       goto *__target;                   \
58     }
59
60 #endif /* i386_HOST_ARCH */
61
62 /* -----------------------------------------------------------------------------
63    Tail calling on x86_64
64    -------------------------------------------------------------------------- */
65
66 #if x86_64_HOST_ARCH
67
68 /*
69   NOTE about __DISCARD__():
70
71   On x86_64 this is necessary to work around bugs in the register
72   variable support in gcc.  Without the __DISCARD__() call, gcc will
73   silently throw away assignements to global register variables that
74   happen before the jump.
75
76   Here's the example:
77
78   extern void g(void);
79   static void f(void) {
80     R1 = g;
81     __DISCARD__()
82     goto *R1;
83   }
84
85   without the dummy function call, gcc throws away the assignment to R1
86   (gcc 3.4.3) gcc bug #
87
88 */
89
90 #define JMP_(cont)                      \
91     {                                   \
92       void *__target;                   \
93       __DISCARD__();                    \
94       __target = (void *)(cont);        \
95       goto *__target;                   \
96     }
97
98 #endif /* x86_64_HOST_ARCH */
99
100 /* -----------------------------------------------------------------------------
101    Tail calling on Sparc
102    -------------------------------------------------------------------------- */
103
104 #ifdef sparc_HOST_ARCH
105
106 #define JMP_(cont)      ((F_) (cont))()
107         /* Oh so happily, the above turns into a "call" instruction,
108            which, on a SPARC, is nothing but a "jmpl" with the
109            return address in %o7 [which we don't care about].
110         */
111
112 /* Don't need these for sparc mangling */
113 #define FB_
114 #define FE_
115
116 #endif /* sparc_HOST_ARCH */
117
118 /* -----------------------------------------------------------------------------
119    Tail calling on Alpha
120    -------------------------------------------------------------------------- */
121
122 #ifdef alpha_HOST_ARCH
123
124 #if IN_STG_CODE
125 register void *_procedure __asm__("$27");
126 #endif
127
128 #define JMP_(cont)                              \
129     do { _procedure = (void *)(cont);           \
130          __DISCARD__();                         \
131          goto *_procedure;                      \
132        } while(0)
133
134 /* Don't need these for alpha mangling */
135 #define FB_
136 #define FE_
137
138 #endif /* alpha_HOST_ARCH */
139
140 /* -----------------------------------------------------------------------------
141    Tail calling on HP
142
143 Description of HP's weird procedure linkage, many thanks to Andy Bennet
144 <andy_bennett@hp.com>:
145
146 I've been digging a little further into the problem of how HP-UX does
147 dynamic procedure calls. My solution in the last e-mail inserting an extra
148 'if' statement into the JMP_ I think is probably the best general solution I
149 can come up with. There are still a few problems with it however: It wont
150 work, if JMP_ ever has to call anything in a shared library, if this is
151 likely to be required it'll need something more elaborate. It also wont work
152 with PA-RISC 2.0 wide mode (64-bit) which uses a different format PLT.
153
154 I had some feedback from someone in HP's compiler lab and the problem
155 relates to the linker on HP-UX, not gcc as I first suspected. The reason the
156 'hsc' executable works is most likely due to a change in 'ld's behaviour for
157 performance reasons between your revision and mine.
158
159 The major issue relating to this is shared libraries and how they are
160 implented under HP-UX. The whole point of the Procedure Label Table (PLT) is
161 to allow a function pointer to hold the address of the function and a
162 pointer to the library's global data lookup table (DLT) used by position
163 independent code (PIC). This makes the PLT absolutely essential for shared
164 library calls. HP has two linker introduced assembly functions for dealing
165 with dynamic calls, $$dyncall and $$dyncall_external. The former does a
166 check to see if the address is a PLT pointer and dereferences if necessary
167 or just calls the address otherwise; the latter skips the check and just
168 does the indirect jump no matter what.
169
170 Since $$dyncall_external runs faster due to its not having the test, the
171 linker nowadays prefers to generate calls to that, rather than $$dyncall. It
172 makes this decision based on the presence of any shared library. If it even
173 smells an sl's existence at link time, it rigs the runtime system to
174 generate PLT references for everything on the assumption that the result
175 will be slightly more efficient. This is what is crashing GHC since the
176 calls it is generating have no understanding of the procedure label proper.
177 The only way to get real addresses is to link everything archive, including
178 system libraries, at which point it assumes you probably are going to be
179 using calls similar to GHC's (its rigged for HP's +ESfic compiler option)
180 but uses $$dyncall if necessary to cope, just in case you aren't.
181
182    -------------------------------------------------------------------------- */
183
184 #ifdef hppa1_1_hp_hpux_TARGET
185
186 #define JMP_(cont)                              \
187     do { void *_procedure = (void *)(cont);     \
188          if (((int) _procedure) & 2)            \
189             _procedure = (void *)(*((int *) (_procedure - 2))); \
190          goto *_procedure;                      \
191        } while(0)
192
193 #endif /* hppa1_1_hp_hpux_TARGET */
194
195 /* -----------------------------------------------------------------------------
196    Tail calling on PowerPC
197    -------------------------------------------------------------------------- */
198
199 #ifdef powerpc_HOST_ARCH
200
201 #define JMP_(cont)                      \
202     {                                   \
203       void *target;                     \
204       target = (void *)(cont);          \
205       __DISCARD__();                    \
206       goto *target;                     \
207     }
208
209 /*
210         The __DISCARD__ is there because Apple's April 2002 Beta of GCC 3.1
211         sometimes generates incorrect code otherwise.
212         It tends to "forget" to update global register variables in the presence
213         of decrement/increment operators:
214         JMP_(*(--Sp)) is wrongly compiled as JMP_(Sp[-1]).
215         Calling __DISCARD__ in between works around this problem.
216 */
217
218 /*
219         I would _love_ to use the following instead,
220         but some versions of Apple's GCC fail to generate code for it
221         if it is called for a casted data pointer - which is exactly what
222         we are going to do...
223
224         #define JMP_(cont)      ((F_) (cont))()
225 */
226
227 #endif /* powerpc_HOST_ARCH */
228
229 #ifdef powerpc64_HOST_ARCH
230 #define JMP_(cont) ((F_) (cont))()
231 #endif
232
233 /* -----------------------------------------------------------------------------
234    Tail calling on IA64
235    -------------------------------------------------------------------------- */
236
237 #ifdef ia64_HOST_ARCH
238
239 /* The compiler can more intelligently decide how to do this.  We therefore
240  * implement it as a call and optimise to a jump at mangle time. */
241 #define JMP_(cont)      ((F_) (cont))(); __asm__ volatile ("--- TAILCALL ---");
242
243 /* Don't emit calls to __DISCARD__ as this causes hassles */
244 #define __DISCARD__()
245
246 #endif
247
248 /* -----------------------------------------------------------------------------
249   FUNBEGIN and FUNEND.
250
251   These are markers indicating the start and end of Real Code in a
252   function.  All instructions between the actual start and end of the
253   function and these markers is shredded by the mangler.
254   -------------------------------------------------------------------------- */
255
256 /*  The following __DISCARD__() has become necessary with gcc 2.96 on x86.
257  *  It prevents gcc from moving stack manipulation code from the function
258  *  body (aka the Real Code) into the function prologue, ie, from moving it
259  *  over the --- BEGIN --- marker.  It should be noted that (like some
260  *  other black magic in GHC's code), there is no essential reason why gcc
261  *  could not move some stack manipulation code across the __DISCARD__() -
262  *  it just doesn't choose to do it at the moment.
263  *  -= chak
264  */
265  
266 #ifndef FB_
267 #define FB_    __asm__ volatile ("--- BEGIN ---"); __DISCARD__ ();
268 #endif
269
270 #ifndef FE_
271 #define FE_    __asm__ volatile ("--- END ---");
272 #endif
273
274 #endif /* !USE_MINIINTERPRETER */
275
276 #endif /* TAILCALLS_H */