[project @ 1999-02-05 16:02:18 by simonm]
[ghc-hetmet.git] / ghc / includes / TailCalls.h
1 /* -----------------------------------------------------------------------------
2  * $Id: TailCalls.h,v 1.3 1999/02/05 16:02:31 simonm 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
40 /* The goto here seems to cause gcc -O2 to delete all the code after
41    it - including the FE_ marker and the epilogue code - exactly what
42    we want! -- SDM
43    */
44
45 #define JMP_(cont)                      \
46     {                                   \
47       void *target;                     \
48       __DISCARD__();                    \
49       target = (void *)(cont);          \
50       goto *target;                     \
51     }
52
53 #endif i386_TARGET_ARCH
54
55 /* -----------------------------------------------------------------------------
56    Tail calling on Sparc
57    -------------------------------------------------------------------------- */
58
59 #ifdef sparc_TARGET_ARCH
60
61 #define JMP_(cont)      ((F_) (cont))()
62         /* Oh so happily, the above turns into a "call" instruction,
63            which, on a SPARC, is nothing but a "jmpl" with the
64            return address in %o7 [which we don't care about].
65         */
66
67 /* Don't need these for sparc mangling */
68 #define FB_
69 #define FE_
70
71 #endif sparc_TARGET_ARCH
72
73 /* -----------------------------------------------------------------------------
74    Tail calling on Alpha
75    -------------------------------------------------------------------------- */
76
77 #ifdef alpha_TARGET_ARCH
78
79 register void *_procedure __asm__("$27");
80
81 #define JMP_(cont)                              \
82     do { _procedure = (void *)(cont);           \
83          goto *_procedure;                      \
84        } while(0)
85
86 /* Don't need these for alpha mangling */
87 #define FB_
88 #define FE_
89
90 #endif alpha_TARGET_ARCH
91
92 /*
93   FUNBEGIN and FUNEND.
94
95   These are markers indicating the start and end of Real Code in a
96   function.  All instructions between the actual start and end of the
97   function and these markers is shredded by the mangler.
98   */
99
100 #ifndef FB_
101 #define FB_    __asm__ volatile ("--- BEGIN ---");
102 #endif
103
104 #ifndef FE_
105 #define FE_    __asm__ volatile ("--- END ---");
106 #endif
107
108 #endif /* !USE_MINIINTERPRETER */
109
110 #endif TAILCALLS_H
111