[project @ 2005-01-28 12:55:17 by simonmar]
[ghc-hetmet.git] / ghc / includes / TailCalls.h
index 8002451..13eea0e 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: TailCalls.h,v 1.7 2001/02/14 10:33:05 simonmar Exp $
+ * $Id: TailCalls.h,v 1.18 2005/01/28 12:55:54 simonmar Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
 
 #ifdef USE_MINIINTERPRETER
 
-#define JMP_(cont) return(stgCast(StgFunPtr,cont))
+#define JMP_(cont) return((StgFunPtr)(cont))
 #define FB_
 #define FE_
 
 #else
 
+extern void __DISCARD__(void);
+
 /* -----------------------------------------------------------------------------
    Tail calling on x86
    -------------------------------------------------------------------------- */
 
-#if i386_TARGET_ARCH
-
-extern void __DISCARD__(void);
+#if i386_HOST_ARCH
 
 /* Note about discard: possibly there to fool GCC into clearing up
    before we do the jump eg. if there are some arguments left on the C
@@ -51,19 +51,34 @@ extern void __DISCARD__(void);
 
 #define JMP_(cont)                     \
     {                                  \
-      void *target;                    \
+      void *__target;                  \
       __DISCARD__();                   \
-      target = (void *)(cont);         \
-      goto *target;                    \
+      __target = (void *)(cont);       \
+      goto *__target;                  \
+    }
+
+#endif /* i386_HOST_ARCH */
+
+/* -----------------------------------------------------------------------------
+   Tail calling on x86_64
+   -------------------------------------------------------------------------- */
+
+#if x86_64_HOST_ARCH
+
+#define JMP_(cont)                     \
+    {                                  \
+      void *__target;                  \
+      __target = (void *)(cont);       \
+      goto *__target;                  \
     }
 
-#endif /* i386_TARGET_ARCH */
+#endif /* x86_64_HOST_ARCH */
 
 /* -----------------------------------------------------------------------------
    Tail calling on Sparc
    -------------------------------------------------------------------------- */
 
-#ifdef sparc_TARGET_ARCH
+#ifdef sparc_HOST_ARCH
 
 #define JMP_(cont)     ((F_) (cont))()
        /* Oh so happily, the above turns into a "call" instruction,
@@ -75,26 +90,29 @@ extern void __DISCARD__(void);
 #define FB_
 #define FE_
 
-#endif /* sparc_TARGET_ARCH */
+#endif /* sparc_HOST_ARCH */
 
 /* -----------------------------------------------------------------------------
    Tail calling on Alpha
    -------------------------------------------------------------------------- */
 
-#ifdef alpha_TARGET_ARCH
+#ifdef alpha_HOST_ARCH
 
+#if IN_STG_CODE
 register void *_procedure __asm__("$27");
+#endif
 
-#define JMP_(cont)                             \
-    do { _procedure = (void *)(cont);          \
-         goto *_procedure;                     \
+#define JMP_(cont)                             \
+    do { _procedure = (void *)(cont);          \
+         __DISCARD__();                                \
+         goto *_procedure;                     \
        } while(0)
 
 /* Don't need these for alpha mangling */
 #define FB_
 #define FE_
 
-#endif /* alpha_TARGET_ARCH */
+#endif /* alpha_HOST_ARCH */
 
 /* -----------------------------------------------------------------------------
    Tail calling on HP
@@ -152,6 +170,59 @@ but uses $$dyncall if necessary to cope, just in case you aren't.
 #endif /* hppa1_1_hp_hpux_TARGET */
 
 /* -----------------------------------------------------------------------------
+   Tail calling on PowerPC
+   -------------------------------------------------------------------------- */
+
+#ifdef powerpc_HOST_ARCH
+
+#define JMP_(cont)                     \
+    {                                  \
+      void *target;                    \
+      target = (void *)(cont);         \
+      __DISCARD__();                   \
+      goto *target;                    \
+    }
+
+/*
+       The __DISCARD__ is there because Apple's April 2002 Beta of GCC 3.1
+       sometimes generates incorrect code otherwise.
+       It tends to "forget" to update global register variables in the presence
+       of decrement/increment operators:
+       JMP_(*(--Sp)) is wrongly compiled as JMP_(Sp[-1]).
+       Calling __DISCARD__ in between works around this problem.
+*/
+
+/*
+       I would _love_ to use the following instead,
+       but some versions of Apple's GCC fail to generate code for it
+       if it is called for a casted data pointer - which is exactly what
+       we are going to do...
+
+       #define JMP_(cont)      ((F_) (cont))()
+*/
+
+#endif /* powerpc_HOST_ARCH */
+
+#ifdef powerpc64_HOST_ARCH
+#define JMP_(cont) ((F_) (cont))()
+#endif
+
+/* -----------------------------------------------------------------------------
+   Tail calling on IA64
+   -------------------------------------------------------------------------- */
+
+#ifdef ia64_HOST_ARCH
+
+/* The compiler can more intelligently decide how to do this.  We therefore
+ * implement it as a call and optimise to a jump at mangle time. */
+#define JMP_(cont)     ((F_) (cont))(); __asm__ volatile ("--- TAILCALL ---");
+
+/* Don't emit calls to __DISCARD__ as this causes hassles */
+#define __DISCARD__()
+
+#endif
+
+/* -----------------------------------------------------------------------------
   FUNBEGIN and FUNEND.
 
   These are markers indicating the start and end of Real Code in a
@@ -168,6 +239,7 @@ but uses $$dyncall if necessary to cope, just in case you aren't.
  *  it just doesn't choose to do it at the moment.
  *  -= chak
  */
 #ifndef FB_
 #define FB_    __asm__ volatile ("--- BEGIN ---"); __DISCARD__ ();
 #endif