/* -----------------------------------------------------------------------------
- * $Id: TailCalls.h,v 1.8 2002/03/26 10:30:44 simonmar Exp $
+ * $Id: TailCalls.h,v 1.11 2002/08/21 22:06:03 ken Exp $
*
* (c) The GHC Team, 1998-1999
*
register void *_procedure __asm__("$27");
-#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 */
{ \
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.