X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FStgCRun.c;h=fc08b50bb3a6d9a44334f97aba50ef4e0140512b;hb=356028e7abbf088d7d71d19997a07a79afbd3c8e;hp=cf210d204fdb04fb74834142d0713038d8394856;hpb=153b9cb9b11e05c4edb1b6bc0a7b972660e41f70;p=ghc-hetmet.git diff --git a/ghc/rts/StgCRun.c b/ghc/rts/StgCRun.c index cf210d2..fc08b50 100644 --- a/ghc/rts/StgCRun.c +++ b/ghc/rts/StgCRun.c @@ -82,17 +82,17 @@ register double fake_f9 __asm__("$f9"); any architecture (using miniinterpreter) -------------------------------------------------------------------------- */ -StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg STG_UNUSED) +StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg STG_UNUSED) { while (f) { - if (RtsFlags[0].DebugFlags.interpreter) { + IF_DEBUG(interpreter, debugBelch("Jumping to "); printPtr((P_)f); fflush(stdout); debugBelch("\n"); - } + ); f = (StgFunPtr) (f)(); } - return (StgThreadReturnCode)R1.i; + return (StgRegTable *)R1.p; } StgFunPtr StgReturn(void) @@ -114,11 +114,17 @@ StgFunPtr StgReturn(void) #ifdef i386_HOST_ARCH -StgThreadReturnCode +#ifdef darwin_TARGET_OS +#define STG_GLOBAL ".globl " +#else +#define STG_GLOBAL ".global " +#endif + +StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg) { unsigned char space[ RESERVED_C_STACK_BYTES + 4*sizeof(void *) ]; - StgThreadReturnCode r; + StgRegTable * r; __asm__ volatile ( /* @@ -135,14 +141,32 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { */ "movl %3,%%ebx\n\t" /* - * grab the function argument from the stack, and jump to it. + * grab the function argument from the stack */ "movl %2,%%eax\n\t" + +#if darwin_TARGET_OS + /* + * Darwin: keep the stack aligned + */ + "subl $12,%%esp\n\t" +#endif + + /* + * jump to it + */ "jmp *%%eax\n\t" - ".global " STG_RETURN "\n" + STG_GLOBAL STG_RETURN "\n" STG_RETURN ":\n\t" +#if darwin_TARGET_OS + /* + * Darwin: keep the stack aligned + */ + "addl $12,%%esp\n\t" +#endif + "movl %%esi, %%eax\n\t" /* Return value in R1 */ /* @@ -177,7 +201,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { #ifdef x86_64_HOST_ARCH -extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg); +extern StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg); static void StgRunIsImplementedInAssembler(void) { @@ -225,7 +249,41 @@ static void StgRunIsImplementedInAssembler(void) "addq %0, %%rsp\n\t" "retq" - : : "i"(RESERVED_C_STACK_BYTES+48 /*stack frame size*/)); + : : "i"(RESERVED_C_STACK_BYTES+48+8 /*stack frame size*/)); + /* + HACK alert! + + The x86_64 ABI specifies that on a procedure call, %rsp is + aligned on a 16-byte boundary + 8. That is, the first + argument on the stack after the return address will be + 16-byte aligned. + + Which should be fine: RESERVED_C_STACK_BYTES+48 is a multiple + of 16 bytes. + + BUT... when we do a C-call from STG land, gcc likes to put the + stack alignment adjustment in the prolog. eg. if we're calling + a function with arguments in regs, gcc will insert 'subq $8,%rsp' + in the prolog, to keep %rsp aligned (the return address is 8 + bytes, remember). The mangler throws away the prolog, so we + lose the stack alignment. + + The hack is to add this extra 8 bytes to our %rsp adjustment + here, so that throughout STG code, %rsp is 16-byte aligned, + ready for a C-call. + + A quick way to see if this is wrong is to compile this code: + + main = System.Exit.exitWith ExitSuccess + + And run it with +RTS -sstderr. The stats code in the RTS, in + particular statsPrintf(), relies on the stack alignment because + it saves the %xmm regs on the stack, so it'll fall over if the + stack isn't aligned, and calling exitWith from Haskell invokes + shutdownHaskellAndExit using a C call. + + Future gcc releases will almost certainly break this hack... + */ } #endif /* x86-64 */ @@ -263,7 +321,7 @@ static void StgRunIsImplementedInAssembler(void) #ifdef sparc_HOST_ARCH -StgThreadReturnCode +StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg) { unsigned char space[RESERVED_C_STACK_BYTES]; @@ -296,7 +354,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { __asm__ volatile ("ld %1,%0" : "=r" (i7) : "m" (((void **)(space))[100])); #endif - return (StgThreadReturnCode)R1.i; + return (StgRegTable *)R1.i; } #endif @@ -331,7 +389,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { #ifdef alpha_HOST_ARCH -StgThreadReturnCode +StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg) { register long real_ra __asm__("$26"); volatile long save_ra; @@ -360,7 +418,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) register StgFunPtr real_pv __asm__("$27"); - StgThreadReturnCode ret; + StgRegTable * ret; save_ra = real_ra; save_gp = real_gp; @@ -433,11 +491,11 @@ StgRun(StgFunPtr f, StgRegTable *basereg) #ifdef hppa1_1_HOST_ARCH -StgThreadReturnCode +StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg) { StgChar space[RESERVED_C_STACK_BYTES+16*sizeof(long)+10*sizeof(double)]; - StgThreadReturnCode ret; + StgRegTable * ret; __asm__ volatile ("ldo %0(%%r30),%%r19\n" "\tstw %%r3, 0(0,%%r19)\n" @@ -529,7 +587,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) #ifdef powerpc_HOST_ARCH -extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg); +extern StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg); #ifdef darwin_HOST_OS static void StgRunIsImplementedInAssembler(void) @@ -647,7 +705,7 @@ static void StgRunIsImplementedInAssembler(void) #ifdef powerpc64_HOST_ARCH #ifdef linux_HOST_OS -extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg); +extern StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg); static void StgRunIsImplementedInAssembler(void) {