/* -----------------------------------------------------------------------------
- * $Id: TailCalls.h,v 1.13 2003/08/29 16:00:26 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_
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
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,
#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); \
#define FB_
#define FE_
-#endif /* alpha_TARGET_ARCH */
+#endif /* alpha_HOST_ARCH */
/* -----------------------------------------------------------------------------
Tail calling on HP
Tail calling on PowerPC
-------------------------------------------------------------------------- */
-#ifdef powerpc_TARGET_ARCH
+#ifdef powerpc_HOST_ARCH
#define JMP_(cont) \
{ \
#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. */