X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fincludes%2FTailCalls.h;h=a61695e7580d0d1d4fc62ec8ceb002f3de7a2faf;hb=423d477bfecd490de1449c59325c8776f91d7aac;hp=8002451b106bb108e04e0f816d52dd73043c83dc;hpb=970b9e8dc1488a2ca260cf20fc8ead86855be772;p=ghc-hetmet.git diff --git a/ghc/includes/TailCalls.h b/ghc/includes/TailCalls.h index 8002451..a61695e 100644 --- a/ghc/includes/TailCalls.h +++ b/ghc/includes/TailCalls.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: TailCalls.h,v 1.7 2001/02/14 10:33:05 simonmar Exp $ + * $Id: TailCalls.h,v 1.16 2004/08/13 13:09:41 simonmar Exp $ * * (c) The GHC Team, 1998-1999 * @@ -16,20 +16,20 @@ #ifdef USE_MINIINTERPRETER -#define JMP_(cont) return(stgCast(StgFunPtr,cont)) +#define JMP_(cont) return((StgFunPtr)(cont)) #define FB_ #define FE_ #else +extern void __DISCARD__(void); + /* ----------------------------------------------------------------------------- Tail calling on x86 -------------------------------------------------------------------------- */ #if i386_TARGET_ARCH -extern void __DISCARD__(void); - /* 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 stack that GCC hasn't popped yet. Also possibly to fool any @@ -51,15 +51,30 @@ extern void __DISCARD__(void); #define JMP_(cont) \ { \ - void *target; \ + void *__target; \ __DISCARD__(); \ - target = (void *)(cont); \ - goto *target; \ + __target = (void *)(cont); \ + goto *__target; \ } #endif /* i386_TARGET_ARCH */ /* ----------------------------------------------------------------------------- + Tail calling on x86_64 + -------------------------------------------------------------------------- */ + +#if x86_64_TARGET_ARCH + +#define JMP_(cont) \ + { \ + void *__target; \ + __target = (void *)(cont); \ + goto *__target; \ + } + +#endif /* x86_64_TARGET_ARCH */ + +/* ----------------------------------------------------------------------------- Tail calling on Sparc -------------------------------------------------------------------------- */ @@ -83,11 +98,14 @@ extern void __DISCARD__(void); #ifdef alpha_TARGET_ARCH +#if IN_STG_CODE register void *_procedure __asm__("$27"); +#endif -#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 */ @@ -152,6 +170,55 @@ but uses $$dyncall if necessary to cope, just in case you aren't. #endif /* hppa1_1_hp_hpux_TARGET */ /* ----------------------------------------------------------------------------- + Tail calling on PowerPC + -------------------------------------------------------------------------- */ + +#ifdef powerpc_TARGET_ARCH + +#define JMP_(cont) \ + { \ + 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 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 */ + +/* ----------------------------------------------------------------------------- + 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. These are markers indicating the start and end of Real Code in a @@ -168,6 +235,7 @@ 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__ (); #endif