X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fincludes%2FTailCalls.h;h=670da9546f75de9df447311bef7f9edbfd293f0e;hb=e6218fe7eff4e34e1a3c823cd4b7aebe09d2d4fb;hp=13eea0e48043f31c678c78475ebcd97bd2bb6859;hpb=153b9cb9b11e05c4edb1b6bc0a7b972660e41f70;p=ghc-hetmet.git diff --git a/ghc/includes/TailCalls.h b/ghc/includes/TailCalls.h index 13eea0e..670da95 100644 --- a/ghc/includes/TailCalls.h +++ b/ghc/includes/TailCalls.h @@ -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 */