[project @ 2005-03-30 09:49:55 by simonmar]
[ghc-hetmet.git] / ghc / rts / StgCRun.c
index 8bb6f08..4d5136f 100644 (file)
@@ -50,7 +50,7 @@
  * in libc.a clobbers $s6.
  */
 #include "ghcconfig.h"
-#ifdef alpha_TARGET_ARCH
+#ifdef alpha_HOST_ARCH
 #define alpha_EXTRA_CAREFUL
 register long   fake_ra __asm__("$26");
 register long   fake_gp __asm__("$29");
@@ -112,7 +112,7 @@ StgFunPtr StgReturn(void)
    x86 architecture
    -------------------------------------------------------------------------- */
 
-#ifdef i386_TARGET_ARCH
+#ifdef i386_HOST_ARCH
 
 StgThreadReturnCode
 StgRun(StgFunPtr f, StgRegTable *basereg) {
@@ -175,7 +175,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
 
    ------------------------------------------------------------------------- */
 
-#ifdef x86_64_TARGET_ARCH
+#ifdef x86_64_HOST_ARCH
 
 extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg);
 
@@ -225,7 +225,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 */
@@ -261,7 +295,7 @@ static void StgRunIsImplementedInAssembler(void)
    Updated info (GHC 4.08.2): not saving %i7 any more (see below).
    -------------------------------------------------------------------------- */
 
-#ifdef sparc_TARGET_ARCH
+#ifdef sparc_HOST_ARCH
 
 StgThreadReturnCode
 StgRun(StgFunPtr f, StgRegTable *basereg) {
@@ -329,7 +363,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
       tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V51_PDF/ARH9MBTE.PDF
    -------------------------------------------------------------------------- */
 
-#ifdef alpha_TARGET_ARCH
+#ifdef alpha_HOST_ARCH
 
 StgThreadReturnCode
 StgRun(StgFunPtr f, StgRegTable *basereg)
@@ -425,13 +459,13 @@ StgRun(StgFunPtr f, StgRegTable *basereg)
     return ret;
 }
 
-#endif /* alpha_TARGET_ARCH */
+#endif /* alpha_HOST_ARCH */
 
 /* -----------------------------------------------------------------------------
    HP-PA architecture
    -------------------------------------------------------------------------- */
 
-#ifdef hppa1_1_TARGET_ARCH
+#ifdef hppa1_1_HOST_ARCH
 
 StgThreadReturnCode
 StgRun(StgFunPtr f, StgRegTable *basereg)
@@ -518,7 +552,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg)
     return ret;
 }
 
-#endif /* hppa1_1_TARGET_ARCH */
+#endif /* hppa1_1_HOST_ARCH */
 
 /* -----------------------------------------------------------------------------
    PowerPC architecture
@@ -527,13 +561,18 @@ StgRun(StgFunPtr f, StgRegTable *basereg)
    
    -------------------------------------------------------------------------- */
 
-#ifdef powerpc_TARGET_ARCH
+#ifdef powerpc_HOST_ARCH
 
 extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg);
 
-#ifdef darwin_TARGET_OS
+#ifdef darwin_HOST_OS
 static void StgRunIsImplementedInAssembler(void)
 {
+#if HAVE_SUBSECTIONS_VIA_SYMBOLS
+            // if the toolchain supports deadstripping, we have to
+            // prevent it here (it tends to get confused here).
+        __asm__ volatile (".no_dead_strip _StgRunIsImplementedInAssembler");
+#endif
        __asm__ volatile (
                "\n.globl _StgRun\n"
                "_StgRun:\n"
@@ -639,9 +678,9 @@ static void StgRunIsImplementedInAssembler(void)
    
    -------------------------------------------------------------------------- */
 
-#ifdef powerpc64_TARGET_ARCH
+#ifdef powerpc64_HOST_ARCH
 
-#ifdef linux_TARGET_OS
+#ifdef linux_HOST_OS
 extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg);
 
 static void StgRunIsImplementedInAssembler(void)
@@ -654,9 +693,20 @@ static void StgRunIsImplementedInAssembler(void)
        // r13 thread local state (never modified, don't need to save)
        // r14-r31 callee-save
        __asm__ volatile (
-               "\t.globl StgRun\n"
-               "\t.type StgRun,@function\n"
+               ".section \".opd\",\"aw\"\n"
+               ".align 3\n"
+               ".globl StgRun\n"
                "StgRun:\n"
+                       "\t.quad\t.StgRun,.TOC.@tocbase,0\n"
+                       "\t.size StgRun,24\n"
+               ".globl StgReturn\n"
+               "StgReturn:\n"
+                       "\t.quad\t.StgReturn,.TOC.@tocbase,0\n"
+                       "\t.size StgReturn,24\n"
+               ".previous\n"
+               ".globl .StgRun\n"
+               ".type .StgRun,@function\n"
+               ".StgRun:\n"
                        "\tmflr 0\n"
                        "\tmr 5, 1\n"
                        "\tstd 0, 16(1)\n"
@@ -703,9 +753,9 @@ static void StgRunIsImplementedInAssembler(void)
                        "\tld 3, 0(3)\n"
                        "\tmtctr 3\n"
                        "\tbctr\n"
-               ".globl StgReturn\n"
-               "\t.type StgReturn,@function\n"
-               "StgReturn:\n"
+               ".globl .StgReturn\n"
+               ".type .StgReturn,@function\n"
+               ".StgReturn:\n"
                        "\tmr 3,14\n"
                        "\tla 5, %0(1)\n" // load address == addi r5, r1, %0
                        "\tld 2, -296(5)\n"
@@ -751,7 +801,7 @@ static void StgRunIsImplementedInAssembler(void)
                        "\tblr\n"
        : : "i"(RESERVED_C_STACK_BYTES+304 /*stack frame size*/));
 }
-#else // linux_TARGET_OS
+#else // linux_HOST_OS
 #error Only linux support for power64 right now.
 #endif
 
@@ -770,7 +820,7 @@ static void StgRunIsImplementedInAssembler(void)
            loc31: saved gp (gcc 3.3 uses this slot)
    -------------------------------------------------------------------------- */
 
-#ifdef ia64_TARGET_ARCH
+#ifdef ia64_HOST_ARCH
 
 /* the memory stack is rarely used, so 16K is excessive */
 #undef RESERVED_C_STACK_BYTES