[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / includes / TailCalls.h
1 /* -----------------------------------------------------------------------------
2  * $Id: TailCalls.h,v 1.2 1998/12/02 13:21:43 simonm Exp $
3  *
4  * Stuff for implementing proper tail jumps.
5  *
6  * ---------------------------------------------------------------------------*/
7
8 #ifndef TAILCALLS_H
9 #define TAILCALLS_H
10
11 /* -----------------------------------------------------------------------------
12    Unmangled tail-jumping: use the mini interpretter.
13    -------------------------------------------------------------------------- */
14
15 #ifdef USE_MINIINTERPRETER
16
17 #define JMP_(cont) return(stgCast(StgFunPtr,cont))
18 #define FB_
19 #define FE_
20
21 #else
22
23 /* -----------------------------------------------------------------------------
24    Tail calling on x86
25    -------------------------------------------------------------------------- */
26
27 #if i386_TARGET_ARCH
28
29 extern void __DISCARD__(void);
30
31 /* Note about discard: possibly there to fool GCC into clearing up
32    before we do the jump eg. if there are some arguments left on the C
33    stack that GCC hasn't popped yet.  Also possibly to fool any
34    optimisations (a function call often acts as a barrier).  Not sure
35    if any of this is necessary now -- SDM
36    */
37
38 /* The goto here seems to cause gcc -O2 to delete all the code after
39    it - including the FE_ marker and the epilogue code - exactly what
40    we want! -- SDM
41    */
42
43 #define JMP_(cont)                      \
44     {                                   \
45       void *target;                     \
46       __DISCARD__();                    \
47       target = (void *)(cont);          \
48       goto *target;                     \
49     }
50
51 #endif i386_TARGET_ARCH
52
53 /* -----------------------------------------------------------------------------
54    Tail calling on Sparc
55    -------------------------------------------------------------------------- */
56
57 #ifdef sparc_TARGET_ARCH
58
59 #define JMP_(cont)      ((F_) (cont))()
60         /* Oh so happily, the above turns into a "call" instruction,
61            which, on a SPARC, is nothing but a "jmpl" with the
62            return address in %o7 [which we don't care about].
63         */
64
65 /* Don't need these for sparc mangling */
66 #define FB_
67 #define FE_
68
69 #endif sparc_TARGET_ARCH
70
71 /* -----------------------------------------------------------------------------
72    Tail calling on Alpha
73    -------------------------------------------------------------------------- */
74
75 #ifdef alpha_TARGET_ARCH
76
77 register void *_procedure __asm__("$27");
78
79 #define JMP_(cont)                              \
80     do { _procedure = (void *)(cont);           \
81          goto *_procedure;                      \
82        } while(0)
83
84 /* Don't need these for alpha mangling */
85 #define FB_
86 #define FE_
87
88 #endif alpha_TARGET_ARCH
89
90 /*
91   FUNBEGIN and FUNEND.
92
93   These are markers indicating the start and end of Real Code in a
94   function.  All instructions between the actual start and end of the
95   function and these markers is shredded by the mangler.
96   */
97
98 #ifndef FB_
99 #define FB_    __asm__ volatile ("--- BEGIN ---");
100 #endif
101
102 #ifndef FE_
103 #define FE_    __asm__ volatile ("--- END ---");
104 #endif
105
106 #endif /* !USE_MINIINTERPRETER */
107
108 #endif TAILCALLS_H
109