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