CNF: Silence pointer fix-up message unless gc debugging is enabled
[ghc.git] / rts / StgCRun.c
index 15f9fd2..2166249 100644 (file)
 #include "StgRun.h"
 #include "Capability.h"
 
-#ifdef DEBUG
+#if defined(DEBUG)
 #include "RtsUtils.h"
 #include "Printer.h"
 #endif
 
-#ifdef USE_MINIINTERPRETER
+#if defined(USE_MINIINTERPRETER)
 
 /* -----------------------------------------------------------------------------
    any architecture (using miniinterpreter)
@@ -90,7 +90,7 @@ StgFunPtr StgReturn(void)
 
 #else /* !USE_MINIINTERPRETER */
 
-#ifdef LEADING_UNDERSCORE
+#if defined(LEADING_UNDERSCORE)
 #define STG_RUN "_StgRun"
 #define STG_RETURN "_StgReturn"
 #else
@@ -114,12 +114,14 @@ StgWord8 *win32AllocStack(void)
    x86 architecture
    -------------------------------------------------------------------------- */
 
-#ifdef i386_HOST_ARCH
+#if defined(i386_HOST_ARCH)
 
-#ifdef darwin_HOST_OS
+#if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
 #define STG_GLOBAL ".globl "
+#define STG_HIDDEN ".private_extern "
 #else
 #define STG_GLOBAL ".global "
+#define STG_HIDDEN ".hidden "
 #endif
 
 /*
@@ -131,7 +133,7 @@ StgWord8 *win32AllocStack(void)
  * ABI requires this (x64, Mac OSX 32bit/64bit) as well as interfacing with
  * other libraries through the FFI.
  *
- * As part of this arrangment we must maitain the stack at a 16-byte boundary
+ * As part of this arrangment we must maintain the stack at a 16-byte boundary
  * - word_size-bytes (so 16n - 4 for i386 and 16n - 8 for x64) on entry to a
  * procedure since both GCC and LLVM expect this. This is because the stack
  * should have been 16-byte boundary aligned and then a call made which pushes
@@ -139,7 +141,7 @@ StgWord8 *win32AllocStack(void)
  * we only jump to other STG procedures, so we maintain the 16n - word_size
  * alignment for these jumps.
  *
- * This gives us binary compatability with LLVM and GCC as well as dealing
+ * This gives us binary compatibility with LLVM and GCC as well as dealing
  * with the FFI. Previously we just maintianed a 16n byte alignment for
  * procedure entry and calls, which led to bugs (see #4211 and #5250).
  *
@@ -157,6 +159,8 @@ StgWord8 *win32AllocStack(void)
  * stack isn't aligned, and calling exitWith from Haskell invokes
  * shutdownHaskellAndExit using a C call.
  *
+ * If you edit the sequence below be sure to update the unwinding information
+ * for stg_stop_thread in StgStartup.cmm.
  */
 
 static void GNUC3_ATTRIBUTE(used)
@@ -164,6 +168,9 @@ StgRunIsImplementedInAssembler(void)
 {
     __asm__ volatile (
         STG_GLOBAL STG_RUN "\n"
+#if !defined(mingw32_HOST_OS)
+        STG_HIDDEN STG_RUN "\n"
+#endif
         STG_RUN ":\n\t"
 
         /*
@@ -234,9 +241,15 @@ StgRunIsImplementedInAssembler(void)
    enough space.  Oh well, it's not much harder this way.
    ------------------------------------------------------------------------- */
 
-#ifdef x86_64_HOST_ARCH
+#if defined(x86_64_HOST_ARCH)
+
+#define STG_GLOBAL ".globl "
 
-extern StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg);
+#if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
+#define STG_HIDDEN ".private_extern "
+#else
+#define STG_HIDDEN ".hidden "
+#endif
 
 static void GNUC3_ATTRIBUTE(used)
 StgRunIsImplementedInAssembler(void)
@@ -245,17 +258,25 @@ StgRunIsImplementedInAssembler(void)
         /*
          * save callee-saves registers on behalf of the STG code.
          */
-        ".globl " STG_RUN "\n"
+        STG_GLOBAL STG_RUN "\n"
+#if !defined(mingw32_HOST_OS)
+        STG_HIDDEN STG_RUN "\n"
+#endif
         STG_RUN ":\n\t"
-        "subq %0, %%rsp\n\t"
+        "subq %1, %%rsp\n\t"
         "movq %%rsp, %%rax\n\t"
-        "addq %0-48, %%rax\n\t"
+        "subq %0, %%rsp\n\t"
         "movq %%rbx,0(%%rax)\n\t"
         "movq %%rbp,8(%%rax)\n\t"
         "movq %%r12,16(%%rax)\n\t"
         "movq %%r13,24(%%rax)\n\t"
         "movq %%r14,32(%%rax)\n\t"
         "movq %%r15,40(%%rax)\n\t"
+#if defined(mingw32_HOST_OS)
+        "movq %%rdi,48(%%rax)\n\t"
+        "movq %%rsi,56(%%rax)\n\t"
+        "movq %%xmm6,64(%%rax)\n\t"
+#endif
         /*
          * Set BaseReg
          */
@@ -282,18 +303,25 @@ StgRunIsImplementedInAssembler(void)
         /*
          * restore callee-saves registers.  (Don't stomp on %%rax!)
          */
-        "movq %%rsp, %%rdx\n\t"
-        "addq %0-48, %%rdx\n\t"
-        "movq 0(%%rdx),%%rbx\n\t"       /* restore the registers saved above */
-        "movq 8(%%rdx),%%rbp\n\t"
-        "movq 16(%%rdx),%%r12\n\t"
-        "movq 24(%%rdx),%%r13\n\t"
-        "movq 32(%%rdx),%%r14\n\t"
-        "movq 40(%%rdx),%%r15\n\t"
         "addq %0, %%rsp\n\t"
+        "movq 0(%%rsp),%%rbx\n\t"       /* restore the registers saved above */
+        "movq 8(%%rsp),%%rbp\n\t"
+        "movq 16(%%rsp),%%r12\n\t"
+        "movq 24(%%rsp),%%r13\n\t"
+        "movq 32(%%rsp),%%r14\n\t"
+        "movq 40(%%rsp),%%r15\n\t"
+#if defined(mingw32_HOST_OS)
+        "movq 48(%%rsp),%%rdi\n\t"
+        "movq 56(%%rsp),%%rsi\n\t"
+        "movq 64(%%rsp),%%xmm6\n\t"
+#endif
+        "addq %1, %%rsp\n\t"
         "retq"
 
-        : : "i"(RESERVED_C_STACK_BYTES + 48 /*stack frame size*/));
+        :
+        : "i"(RESERVED_C_STACK_BYTES),
+          "i"(STG_RUN_STACK_FRAME_SIZE /* stack frame size */)
+        );
         /*
          * See Note [Stack Alignment on X86]
          */
@@ -332,7 +360,7 @@ StgRunIsImplementedInAssembler(void)
    Updated info (GHC 4.08.2): not saving %i7 any more (see below).
    -------------------------------------------------------------------------- */
 
-#ifdef sparc_HOST_ARCH
+#if defined(sparc_HOST_ARCH)
 
 StgRegTable *
 StgRun(StgFunPtr f, StgRegTable *basereg) {
@@ -381,21 +409,32 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
    Everything is in assembler, so we don't have to deal with GCC...
    -------------------------------------------------------------------------- */
 
-#ifdef powerpc_HOST_ARCH
+#if defined(powerpc_HOST_ARCH)
+
+#define STG_GLOBAL ".globl "
+
+#if defined(darwin_HOST_OS)
+#define STG_HIDDEN ".private_extern "
+#else
+#define STG_HIDDEN ".hidden "
+#endif
+
+#if defined(aix_HOST_OS)
 
-extern StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg);
+// implementation is in StgCRunAsm.S
 
-#ifdef darwin_HOST_OS
+#elif defined(darwin_HOST_OS)
 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");
+        __asm__ volatile (".no_dead_strip _StgRunIsImplementedInAssembler\n");
 #endif
         __asm__ volatile (
-                "\n.globl _StgRun\n"
-                "_StgRun:\n"
+                STG_GLOBAL STG_RUN "\n"
+                STG_HIDDEN STG_RUN "\n"
+                STG_RUN ":\n"
                 "\tmflr r0\n"
                 "\tbl saveFP # f14\n"
                 "\tstmw r13,-220(r1)\n"
@@ -429,6 +468,7 @@ StgRunIsImplementedInAssembler(void)
 {
         __asm__ volatile (
                 "\t.globl StgRun\n"
+                "\t.hidden StgRun\n"
                 "\t.type StgRun,@function\n"
                 "StgRun:\n"
                 "\tmflr 0\n"
@@ -498,11 +538,9 @@ StgRunIsImplementedInAssembler(void)
    Everything is in assembler, so we don't have to deal with GCC...
    -------------------------------------------------------------------------- */
 
-#ifdef powerpc64_HOST_ARCH
-
-#ifdef linux_HOST_OS
-extern StgRegTable * StgRun(StgFunPtr f, StgRegTable *basereg);
+#if defined(powerpc64_HOST_ARCH)
 
+#if defined(linux_HOST_OS)
 static void GNUC3_ATTRIBUTE(used)
 StgRunIsImplementedInAssembler(void)
 {
@@ -517,6 +555,7 @@ StgRunIsImplementedInAssembler(void)
                 ".section \".opd\",\"aw\"\n"
                 ".align 3\n"
                 ".globl StgRun\n"
+                ".hidden StgRun\n"
                 "StgRun:\n"
                 "\t.quad\t.StgRun,.TOC.@tocbase,0\n"
                 "\t.size StgRun,24\n"
@@ -624,16 +663,24 @@ StgRunIsImplementedInAssembler(void)
 }
 
 #else // linux_HOST_OS
-#error Only linux support for power64 right now.
+#error Only Linux support for power64 right now.
 #endif
 
 #endif
 
+#if defined(powerpc64le_HOST_ARCH)
+/* -----------------------------------------------------------------------------
+   PowerPC 64 little endian architecture
+
+   Really everything is in assembler, so we don't have to deal with GCC...
+   -------------------------------------------------------------------------- */
+#endif
+
 /* -----------------------------------------------------------------------------
    ARM architecture
    -------------------------------------------------------------------------- */
 
-#ifdef arm_HOST_ARCH
+#if defined(arm_HOST_ARCH)
 
 #if defined(__thumb__)
 #define THUMB_FUNC ".thumb\n\t.thumb_func\n\t"
@@ -648,13 +695,13 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
         /*
          * save callee-saves registers on behalf of the STG code.
          */
-        "stmfd sp!, {r4-r10, fp, ip, lr}\n\t"
+        "stmfd sp!, {r4-r11, ip, lr}\n\t"
 #if !defined(arm_HOST_ARCH_PRE_ARMv6)
         "vstmdb sp!, {d8-d11}\n\t"
 #endif
         /*
          * allocate some space for Stg machine's temporary storage.
-         * Note: RESERVER_C_STACK_BYTES has to be a round number here or
+         * Note: RESERVED_C_STACK_BYTES has to be a round number here or
          * the assembler can't assemble it.
          */
         "sub sp, sp, %3\n\t"
@@ -667,9 +714,11 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
          */
         "bx %1\n\t"
 
-        ".global " STG_RETURN "\n\t"
+        ".globl " STG_RETURN "\n\t"
         THUMB_FUNC
+#if !defined(ios_HOST_OS)
         ".type " STG_RETURN ", %%function\n"
+#endif
         STG_RETURN ":\n\t"
         /*
          * Free the space we allocated
@@ -685,7 +734,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
 #if !defined(arm_HOST_ARCH_PRE_ARMv6)
         "vldmia sp!, {d8-d11}\n\t"
 #endif
-        "ldmfd sp!, {r4-r10, fp, ip, lr}\n\t"
+        "ldmfd sp!, {r4-r11, ip, lr}\n\t"
       : "=r" (r)
       : "r" (f), "r" (basereg), "i" (RESERVED_C_STACK_BYTES)
 #if !defined(__thumb__)
@@ -701,11 +750,91 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
            includes/stg/MachRegs.h Please note that Haskell code is
            compiled by GHC/LLVM into ARM code (not Thumb!), at least
            as of February 2012 */
-      : "%r4", "%r5", "%r6", "%r8", "%r9", "%r10", "%fp", "%ip", "%lr"
+      : "%r4", "%r5", "%r6", "%r8", "%r9", "%r10", "%11", "%ip", "%lr"
+#endif
+    );
+    return r;
+}
+#endif
+
+#if defined(aarch64_HOST_ARCH)
+
+StgRegTable *
+StgRun(StgFunPtr f, StgRegTable *basereg) {
+    StgRegTable * r;
+    __asm__ volatile (
+        /*
+         * Save callee-saves registers on behalf of the STG code.
+         * Floating point registers only need the bottom 64 bits preserved.
+         * We need to use the the names x16, x17, x29 and x30 instead of ip0
+         * ip1, fp and lp because one of either clang or gcc doesn't understand
+         * the later names.
+         */
+        "stp x29,  x30,  [sp, #-16]!\n\t"
+        "mov x29, sp\n\t"
+        "stp x16, x17, [sp, #-16]!\n\t"
+        "stp x19, x20, [sp, #-16]!\n\t"
+        "stp x21, x22, [sp, #-16]!\n\t"
+        "stp x23, x24, [sp, #-16]!\n\t"
+        "stp x25, x26, [sp, #-16]!\n\t"
+        "stp x27, x28, [sp, #-16]!\n\t"
+        "stp d8,  d9,  [sp, #-16]!\n\t"
+        "stp d10, d11, [sp, #-16]!\n\t"
+        "stp d12, d13, [sp, #-16]!\n\t"
+        "stp d14, d15, [sp, #-16]!\n\t"
+
+        /*
+         * allocate some space for Stg machine's temporary storage.
+         * Note: RESERVED_C_STACK_BYTES has to be a round number here or
+         * the assembler can't assemble it.
+         */
+        "sub sp, sp, %3\n\t"
+        /*
+         * Set BaseReg
+         */
+        "mov x19, %2\n\t"
+        /*
+         * Jump to function argument.
+         */
+        "br %1\n\t"
+
+        ".globl " STG_RETURN "\n\t"
+#if !defined(ios_HOST_OS)
+        ".type " STG_RETURN ", %%function\n"
 #endif
+        STG_RETURN ":\n\t"
+        /*
+         * Free the space we allocated
+         */
+        "add sp, sp, %3\n\t"
+        /*
+         * Return the new register table, taking it from Stg's R1 (ARM64's R22).
+         */
+        "mov %0, x22\n\t"
+        /*
+         * restore callee-saves registers.
+         */
+
+        "ldp d14, d15, [sp], #16\n\t"
+        "ldp d12, d13, [sp], #16\n\t"
+        "ldp d10, d11, [sp], #16\n\t"
+        "ldp d8,  d9,  [sp], #16\n\t"
+        "ldp x27, x28, [sp], #16\n\t"
+        "ldp x25, x26, [sp], #16\n\t"
+        "ldp x23, x24, [sp], #16\n\t"
+        "ldp x21, x22, [sp], #16\n\t"
+        "ldp x19, x20, [sp], #16\n\t"
+        "ldp x16, x17, [sp], #16\n\t"
+        "ldp x29,  x30,  [sp], #16\n\t"
+
+      : "=r" (r)
+      : "r" (f), "r" (basereg), "i" (RESERVED_C_STACK_BYTES)
+        : "%x19", "%x20", "%x21", "%x22", "%x23", "%x24", "%x25", "%x26", "%x27", "%x28",
+          "%x16", "%x17", "%x30"
     );
     return r;
 }
+
 #endif
 
 #endif /* !USE_MINIINTERPRETER */