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