update submodules for GHC.HetMet.GArrow -> Control.GArrow renaming
[ghc-hetmet.git] / rts / Adjustor.c
index 8c38df6..607c0b8 100644 (file)
@@ -38,15 +38,25 @@ Haskell side.
 
 #include "PosixSource.h"
 #include "Rts.h"
-#include "RtsExternal.h"
-#include "RtsUtils.h"
-#include <stdlib.h>
 
-#if defined(USE_LIBFFI)
+#include "RtsUtils.h"
+#include "Stable.h"
 
-#include <ffi.h>
+#if defined(USE_LIBFFI_FOR_ADJUSTORS)
+#include "ffi.h"
 #include <string.h>
+#endif
+
+#if defined(i386_HOST_ARCH) && defined(darwin_HOST_OS)
+extern void adjustorCode(void);
+#elif defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH)
+// from AdjustorAsm.s
+// not declared as a function so that AIX-style
+// fundescs can never get in the way.
+extern void *adjustorCode;
+#endif
 
+#if defined(USE_LIBFFI_FOR_ADJUSTORS)
 void
 freeHaskellFunctionPtr(void* ptr)
 {
@@ -90,6 +100,7 @@ createAdjustor (int cconv,
     ffi_type *result_type;
     ffi_closure *cl;
     int r, abi;
+    void *code;
 
     n_args = strlen(typeString) - 1;
     cif = stgMallocBytes(sizeof(ffi_cif), "createAdjustor");
@@ -100,7 +111,7 @@ createAdjustor (int cconv,
         arg_types[i] = char_to_ffi_type(typeString[i+1]);
     }
     switch (cconv) {
-#ifdef mingw32_TARGET_OS
+#ifdef mingw32_HOST_OS
     case 0: /* stdcall */
         abi = FFI_STDCALL;
         break;
@@ -115,13 +126,15 @@ createAdjustor (int cconv,
     r = ffi_prep_cif(cif, abi, n_args, result_type, arg_types);
     if (r != FFI_OK) barf("ffi_prep_cif failed: %d", r);
     
-    // ToDo: use ffi_closure_alloc()
-    cl = allocateExec(sizeof(ffi_closure));
+    cl = allocateExec(sizeof(ffi_closure), &code);
+    if (cl == NULL) {
+        barf("createAdjustor: failed to allocate memory");
+    }
 
     r = ffi_prep_closure(cl, cif, (void*)wptr, hptr/*userdata*/);
     if (r != FFI_OK) barf("ffi_prep_closure failed: %d", r);
 
-    return (void*)cl;
+    return (void*)code;
 }
 
 #else // To end of file...
@@ -207,12 +220,12 @@ stgAllocStable(size_t size_in_bytes, StgStablePtr *stable)
   nat data_size_in_words, total_size_in_words;
   
   /* round up to a whole number of words */
-  data_size_in_words  = (size_in_bytes + sizeof(W_) + 1) / sizeof(W_);
+  data_size_in_words  = ROUNDUP_BYTES_TO_WDS(size_in_bytes);
   total_size_in_words = sizeofW(StgArrWords) + data_size_in_words;
   
   /* allocate and fill it in */
   arr = (StgArrWords *)allocate(total_size_in_words);
-  SET_ARR_HDR(arr, &stg_ARR_WORDS_info, CCCS, data_size_in_words);
+  SET_ARR_HDR(arr, &stg_ARR_WORDS_info, CCCS, size_in_bytes);
  
   /* obtain a stable ptr */
   *stable = getStablePtr((StgPtr)arr);
@@ -291,7 +304,7 @@ typedef struct AdjustorStub {
 } AdjustorStub;
 #endif
 
-#if defined(darwin_HOST_OS) || defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH)
+#if (defined(i386_HOST_ARCH) && defined(darwin_HOST_OS)) || defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH)
 static int totalArgumentSize(char *typeString)
 {
     int sz = 0;
@@ -329,6 +342,7 @@ createAdjustor(int cconv, StgStablePtr hptr,
               )
 {
   void *adjustor = NULL;
+  void *code;
 
   switch (cconv)
   {
@@ -346,7 +360,7 @@ createAdjustor(int cconv, StgStablePtr hptr,
      <c>:      ff e0             jmp    %eax              # and jump to it.
                # the callee cleans up the stack
     */
-    adjustor = allocateExec(14);
+    adjustor = allocateExec(14,&code);
     {
        unsigned char *const adj_code = (unsigned char *)adjustor;
        adj_code[0x00] = (unsigned char)0x58;  /* popl %eax  */
@@ -391,7 +405,7 @@ createAdjustor(int cconv, StgStablePtr hptr,
     That's (thankfully) the case here with the restricted set of 
     return types that we support.
   */
-    adjustor = allocateExec(17);
+    adjustor = allocateExec(17,&code);
     {
        unsigned char *const adj_code = (unsigned char *)adjustor;
 
@@ -416,10 +430,9 @@ createAdjustor(int cconv, StgStablePtr hptr,
           
           We offload most of the work to AdjustorAsm.S.
         */
-        AdjustorStub *adjustorStub = allocateExec(sizeof(AdjustorStub));
+        AdjustorStub *adjustorStub = allocateExec(sizeof(AdjustorStub),&code);
         adjustor = adjustorStub;
 
-        extern void adjustorCode(void);
         int sz = totalArgumentSize(typeString);
         
         adjustorStub->call[0] = 0xe8;
@@ -505,6 +518,7 @@ createAdjustor(int cconv, StgStablePtr hptr,
     {  
        int i = 0;
        char *c;
+       StgWord8 *adj_code;
 
        // determine whether we have 6 or more integer arguments,
        // and therefore need to flush one to the stack.
@@ -514,35 +528,37 @@ createAdjustor(int cconv, StgStablePtr hptr,
        }
 
        if (i < 6) {
-           adjustor = allocateExec(0x30);
-
-           *(StgInt32 *)adjustor        = 0x49c1894d;
-           *(StgInt32 *)(adjustor+0x4)  = 0x8948c889;
-           *(StgInt32 *)(adjustor+0x8)  = 0xf28948d1;
-           *(StgInt32 *)(adjustor+0xc)  = 0x48fe8948;
-           *(StgInt32 *)(adjustor+0x10) = 0x000a3d8b;
-           *(StgInt32 *)(adjustor+0x14) = 0x25ff0000;
-           *(StgInt32 *)(adjustor+0x18) = 0x0000000c;
-           *(StgInt64 *)(adjustor+0x20) = (StgInt64)hptr;
-           *(StgInt64 *)(adjustor+0x28) = (StgInt64)wptr;
+           adjustor = allocateExec(0x30,&code);
+            adj_code = (StgWord8*)adjustor;
+
+           *(StgInt32 *)adj_code        = 0x49c1894d;
+           *(StgInt32 *)(adj_code+0x4)  = 0x8948c889;
+           *(StgInt32 *)(adj_code+0x8)  = 0xf28948d1;
+           *(StgInt32 *)(adj_code+0xc)  = 0x48fe8948;
+           *(StgInt32 *)(adj_code+0x10) = 0x000a3d8b;
+           *(StgInt32 *)(adj_code+0x14) = 0x25ff0000;
+           *(StgInt32 *)(adj_code+0x18) = 0x0000000c;
+           *(StgInt64 *)(adj_code+0x20) = (StgInt64)hptr;
+           *(StgInt64 *)(adj_code+0x28) = (StgInt64)wptr;
        }
        else
        {
-           adjustor = allocateExec(0x40);
-
-           *(StgInt32 *)adjustor        = 0x35ff5141;
-           *(StgInt32 *)(adjustor+0x4)  = 0x00000020;
-           *(StgInt32 *)(adjustor+0x8)  = 0x49c1894d;
-           *(StgInt32 *)(adjustor+0xc)  = 0x8948c889;
-           *(StgInt32 *)(adjustor+0x10) = 0xf28948d1;
-           *(StgInt32 *)(adjustor+0x14) = 0x48fe8948;
-           *(StgInt32 *)(adjustor+0x18) = 0x00123d8b;
-           *(StgInt32 *)(adjustor+0x1c) = 0x25ff0000;
-           *(StgInt32 *)(adjustor+0x20) = 0x00000014;
+           adjustor = allocateExec(0x40,&code);
+            adj_code = (StgWord8*)adjustor;
+
+           *(StgInt32 *)adj_code        = 0x35ff5141;
+           *(StgInt32 *)(adj_code+0x4)  = 0x00000020;
+           *(StgInt32 *)(adj_code+0x8)  = 0x49c1894d;
+           *(StgInt32 *)(adj_code+0xc)  = 0x8948c889;
+           *(StgInt32 *)(adj_code+0x10) = 0xf28948d1;
+           *(StgInt32 *)(adj_code+0x14) = 0x48fe8948;
+           *(StgInt32 *)(adj_code+0x18) = 0x00123d8b;
+           *(StgInt32 *)(adj_code+0x1c) = 0x25ff0000;
+           *(StgInt32 *)(adj_code+0x20) = 0x00000014;
            
-           *(StgInt64 *)(adjustor+0x28) = (StgInt64)obscure_ccall_ret_code;
-           *(StgInt64 *)(adjustor+0x30) = (StgInt64)hptr;
-           *(StgInt64 *)(adjustor+0x38) = (StgInt64)wptr;
+           *(StgInt64 *)(adj_code+0x28) = (StgInt64)obscure_ccall_ret_code;
+           *(StgInt64 *)(adj_code+0x30) = (StgInt64)hptr;
+           *(StgInt64 *)(adj_code+0x38) = (StgInt64)wptr;
        }
     }
 #elif defined(sparc_HOST_ARCH)
@@ -575,7 +591,7 @@ createAdjustor(int cconv, StgStablePtr hptr,
      similarly, and local variables should be accessed via %fp, not %sp. In a
      nutshell: This should work! (Famous last words! :-)
   */
-    adjustor = allocateExec(4*(11+1));
+    adjustor = allocateExec(4*(11+1),&code);
     {
         unsigned long *const adj_code = (unsigned long *)adjustor;
 
@@ -652,7 +668,7 @@ TODO: Depending on how much allocation overhead stgMallocBytes uses for
       4 bytes (getting rid of the nop), hence saving memory. [ccshan]
   */
     ASSERT(((StgWord64)wptr & 3) == 0);
-    adjustor = allocateExec(48);
+    adjustor = allocateExec(48,&code);
     {
        StgWord64 *const code = (StgWord64 *)adjustor;
 
@@ -716,7 +732,7 @@ TODO: Depending on how much allocation overhead stgMallocBytes uses for
                 }
                 else
                 {
-                    if((t == 'l' || t == 'L' || t == 'd')
+                    if(t == 'l' || t == 'L' || t == 'd')
                     {
                         if(src_offset % 8)
                             src_offset += 4;
@@ -757,7 +773,7 @@ TODO: Depending on how much allocation overhead stgMallocBytes uses for
             */
                     // allocate space for at most 4 insns per parameter
                     // plus 14 more instructions.
-        adjustor = allocateExec(4 * (4*n + 14));
+        adjustor = allocateExec(4 * (4*n + 14),&code);
         code = (unsigned*)adjustor;
         
         *code++ = 0x48000008; // b *+8
@@ -908,15 +924,10 @@ TODO: Depending on how much allocation overhead stgMallocBytes uses for
         AdjustorStub *adjustorStub;
         int sz = 0, extra_sz, total_sz;
 
-            // from AdjustorAsm.s
-            // not declared as a function so that AIX-style
-            // fundescs can never get in the way.
-        extern void *adjustorCode;
-        
 #ifdef FUNDESCS
         adjustorStub = stgMallocBytes(sizeof(AdjustorStub), "createAdjustor");
 #else
-        adjustorStub = allocateExec(sizeof(AdjustorStub));
+        adjustorStub = allocateExec(sizeof(AdjustorStub),&code);
 #endif
         adjustor = adjustorStub;
             
@@ -1089,7 +1100,7 @@ TODO: Depending on how much allocation overhead stgMallocBytes uses for
   }
 
   /* Have fun! */
-  return adjustor;
+  return code;
 }
 
 
@@ -1117,9 +1128,9 @@ if ( *(unsigned char*)ptr != 0xe8 ) {
  freeStablePtr(((AdjustorStub*)ptr)->hptr);
 #elif defined(x86_64_HOST_ARCH)
  if ( *(StgWord16 *)ptr == 0x894d ) {
-     freeStablePtr(*(StgStablePtr*)(ptr+0x20));
+     freeStablePtr(*(StgStablePtr*)((StgWord8*)ptr+0x20));
  } else if ( *(StgWord16 *)ptr == 0x5141 ) {
-     freeStablePtr(*(StgStablePtr*)(ptr+0x30));
+     freeStablePtr(*(StgStablePtr*)((StgWord8*)ptr+0x30));
  } else {
    errorBelch("freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
    return;
@@ -1147,7 +1158,6 @@ if ( *(unsigned char*)ptr != 0xe8 ) {
  }
  freeStablePtr(((StgStablePtr*)ptr)[1]);
 #elif defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH)
- extern void* adjustorCode;
  if ( ((AdjustorStub*)ptr)->code != (StgFunPtr) &adjustorCode ) {
    errorBelch("freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
    return;
@@ -1167,9 +1177,10 @@ if ( *(unsigned char*)ptr != 0xe8 ) {
 #else
  ASSERT(0);
 #endif
- *((unsigned char*)ptr) = '\0';
+ // Can't write to this memory, it is only executable:
+ // *((unsigned char*)ptr) = '\0';
 
  freeExec(ptr);
 }
 
-#endif // !USE_LIBFFI
+#endif // !USE_LIBFFI_FOR_ADJUSTORS