[project @ 2005-11-25 13:10:04 by simonmar]
[ghc-hetmet.git] / ghc / includes / TailCalls.h
index 13eea0e..53db254 100644 (file)
@@ -1,5 +1,4 @@
 /* -----------------------------------------------------------------------------
- * $Id: TailCalls.h,v 1.18 2005/01/28 12:55:54 simonmar Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -65,11 +64,31 @@ extern void __DISCARD__(void);
 
 #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_HOST_ARCH */
@@ -230,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
@@ -239,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_