[project @ 2005-11-18 15:24:12 by simonmar]
[ghc-hetmet.git] / ghc / includes / TailCalls.h
index bdcc400..53db254 100644 (file)
@@ -1,5 +1,4 @@
 /* -----------------------------------------------------------------------------
- * $Id: TailCalls.h,v 1.15 2003/10/12 13:24:52 igloo Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -16,7 +15,7 @@
 
 #ifdef USE_MINIINTERPRETER
 
-#define JMP_(cont) return(stgCast(StgFunPtr,cont))
+#define JMP_(cont) return((StgFunPtr)(cont))
 #define FB_
 #define FE_
 
@@ -28,7 +27,7 @@ extern void __DISCARD__(void);
    Tail calling on x86
    -------------------------------------------------------------------------- */
 
-#if i386_TARGET_ARCH
+#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
@@ -57,28 +56,48 @@ extern void __DISCARD__(void);
       goto *__target;                  \
     }
 
-#endif /* i386_TARGET_ARCH */
+#endif /* i386_HOST_ARCH */
 
 /* -----------------------------------------------------------------------------
    Tail calling on x86_64
    -------------------------------------------------------------------------- */
 
-#if x86_64_TARGET_ARCH
+#if x86_64_HOST_ARCH
+
+/*
+  NOTE about __DISCARD__():
+
+  On x86_64 this is necessary to work around bugs in the register
+  variable support in gcc.  Without the __DISCARD__() call, gcc will
+  silently throw away assignements to global register variables that
+  happen before the jump.
+
+  Here's the example:
+
+  extern void g(void);
+  static void f(void) {
+    R1 = g;
+    __DISCARD__()
+    goto *R1;
+  }
+
+  without the dummy function call, gcc throws away the assignment to R1
+  (gcc 3.4.3) gcc bug #20359.
+*/
 
 #define JMP_(cont)                     \
     {                                  \
-      void *__target;                  \
-      __target = (void *)(cont);       \
-      goto *__target;                  \
+      __DISCARD__();                   \
+      goto *(void *)(cont);                    \
     }
 
-#endif /* x86_64_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,
@@ -90,13 +109,13 @@ 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");
@@ -112,7 +131,7 @@ register void *_procedure __asm__("$27");
 #define FB_
 #define FE_
 
-#endif /* alpha_TARGET_ARCH */
+#endif /* alpha_HOST_ARCH */
 
 /* -----------------------------------------------------------------------------
    Tail calling on HP
@@ -173,7 +192,7 @@ but uses $$dyncall if necessary to cope, just in case you aren't.
    Tail calling on PowerPC
    -------------------------------------------------------------------------- */
 
-#ifdef powerpc_TARGET_ARCH
+#ifdef powerpc_HOST_ARCH
 
 #define JMP_(cont)                     \
     {                                  \
@@ -201,13 +220,17 @@ but uses $$dyncall if necessary to cope, just in case you aren't.
        #define JMP_(cont)      ((F_) (cont))()
 */
 
-#endif /* powerpc_TARGET_ARCH */
+#endif /* powerpc_HOST_ARCH */
+
+#ifdef powerpc64_HOST_ARCH
+#define JMP_(cont) ((F_) (cont))()
+#endif
 
 /* -----------------------------------------------------------------------------
    Tail calling on IA64
    -------------------------------------------------------------------------- */
 
-#ifdef ia64_TARGET_ARCH
+#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. */
@@ -226,6 +249,8 @@ but uses $$dyncall if necessary to cope, just in case you aren't.
   function and these markers is shredded by the mangler.
   -------------------------------------------------------------------------- */
 
+#ifndef FB_
+#if __GNUC__ < 3
 /*  The following __DISCARD__() has become necessary with gcc 2.96 on x86.
  *  It prevents gcc from moving stack manipulation code from the function
  *  body (aka the Real Code) into the function prologue, ie, from moving it
@@ -235,9 +260,17 @@ 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__ ();
+#else
+/* The __DISCARD__() doesn't appear to be necessary with gcc >= 3.2 at
+ * least, and it does cause some difficulty, preventing gcc from
+ * optimising around the beginning of the function.  In particular,
+ * gcc leaves some stack assignments in the prologue when the call is
+ * present. --SDM
+
+ */
+#define FB_    __asm__ volatile ("--- BEGIN ---");
+#endif
 #endif
 
 #ifndef FE_