[project @ 2000-11-07 10:42:55 by simonmar]
[ghc-hetmet.git] / ghc / includes / TailCalls.h
1 /* -----------------------------------------------------------------------------
2  * $Id: TailCalls.h,v 1.6 2000/11/07 10:42:56 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 /* -----------------------------------------------------------------------------
26    Tail calling on x86
27    -------------------------------------------------------------------------- */
28
29 #if i386_TARGET_ARCH
30
31 extern void __DISCARD__(void);
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 Sparc
64    -------------------------------------------------------------------------- */
65
66 #ifdef sparc_TARGET_ARCH
67
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].
72         */
73
74 /* Don't need these for sparc mangling */
75 #define FB_
76 #define FE_
77
78 #endif /* sparc_TARGET_ARCH */
79
80 /* -----------------------------------------------------------------------------
81    Tail calling on Alpha
82    -------------------------------------------------------------------------- */
83
84 #ifdef alpha_TARGET_ARCH
85
86 register void *_procedure __asm__("$27");
87
88 #define JMP_(cont)                              \
89     do { _procedure = (void *)(cont);           \
90          goto *_procedure;                      \
91        } while(0)
92
93 /* Don't need these for alpha mangling */
94 #define FB_
95 #define FE_
96
97 #endif /* alpha_TARGET_ARCH */
98
99 /* -----------------------------------------------------------------------------
100    Tail calling on HP
101    -------------------------------------------------------------------------- */
102
103 #ifdef hppa1_1_hp_hpux_TARGET
104
105 #define JMP_(cont)                              \
106     do { void *_procedure = (void *)(cont);     \
107          goto *_procedure;                      \
108        } while(0)
109
110 #endif /* hppa1_1_hp_hpux_TARGET */
111
112 /* -----------------------------------------------------------------------------
113   FUNBEGIN and FUNEND.
114
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   -------------------------------------------------------------------------- */
119
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.
127  *  -= chak
128  */
129 #ifndef FB_
130 #define FB_    __asm__ volatile ("--- BEGIN ---"); __DISCARD__ ();
131 #endif
132
133 #ifndef FE_
134 #define FE_    __asm__ volatile ("--- END ---");
135 #endif
136
137 #endif /* !USE_MINIINTERPRETER */
138
139 #endif /* TAILCALLS_H */