[project @ 2002-07-16 10:58:16 by simonmar]
[ghc-hetmet.git] / ghc / includes / TailCalls.h
index 92d4f72..2d3f36c 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: TailCalls.h,v 1.8 2002/03/26 10:30:44 simonmar Exp $
+ * $Id: TailCalls.h,v 1.10 2002/06/03 13:08:41 matthewc Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -161,19 +161,44 @@ but uses $$dyncall if necessary to cope, just in case you aren't.
     {                                  \
       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 GCC fails to generate code for it if it is called for a casted
-       data pointer - which is exactly what we are going to do...
+       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_TARGET_ARCH */
 
-#endif /* sparc_TARGET_ARCH */
+/* -----------------------------------------------------------------------------
+   Tail calling on IA64
+   -------------------------------------------------------------------------- */
+
+#ifdef ia64_TARGET_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.