Package: ocaml-ctypes
Version: 0.7.0-1
Severity: important
Tags: sid + patch + fixed-upstream
Justification: FTBFS
User: debian-m...@lists.debian.org
Usertags: mips-patch
Forwarded: 
https://github.com/ocamllabs/ocaml-ctypes/issues/441<https://github.com/ocamllabs/ocaml-ctypes/issues/441#issuecomment-245922709>

Hi,

Package ocaml-ctypes FTBFS for mips64el on testing with following error:
> =============================================================================
> Error: Higher-order tests:1:test_higher_order_basic (stubs).
>
> File "/«PKGBUILDDIR»/_build/oUnit-Higher-order tests-mipsel-sil-01#00.log", 
> line 26, characters 1-1:
> Error: Higher-order tests:1:test_higher_order_basic (stubs) (in the log).
>
> (Program not linked with -g, cannot print stack backtrace)
>
> not equal
> ------------------------------------------------------------------------------
> ==============================================================================
> Error: Higher-order tests:0:test_higher_order_basic (foreign).
>
> File "/«PKGBUILDDIR»/_build/oUnit-Higher-order tests-mipsel-sil-01#00.log", 
> line 20, characters 1-1:
> Error: Higher-order tests:0:test_higher_order_basic (foreign) (in the log).
>
> (Program not linked with -g, cannot print stack backtrace)
>
> not equal
> ------------------------------------------------------------------------------

Full log: 
https://buildd.debian.org/status/fetch.php?pkg=ocaml-ctypes&arch=mips64el&ver=0.7.0-1&stamp=1470056946

This bug was reported and fixed upstream: 
https://github.com/ocamllabs/ocaml-ctypes/issues/441<https://github.com/ocamllabs/ocaml-ctypes/issues/441#issuecomment-245922709>

The tests are failing because there is a problem with integers smaller than 
word-size. They was always zero-extended, never sign-extended.

The attached patch is a back-ported pull request 
(https://github.com/ocamllabs/ocaml-ctypes/pull/456) created by Andreas 
Hauptmann (fdopen) for this bug.
With this patch I was able to build ocaml-ctype successfully for mips64el.

Thanks,
Daniel
--- ocaml-ctypes-0.7.0.orig/src/ctypes-foreign-base/ffi_call_stubs.c
+++ ocaml-ctypes-0.7.0/src/ctypes-foreign-base/ffi_call_stubs.c
@@ -256,9 +256,11 @@ value ctypes_add_argument(value callspec
   CAMLreturn(Val_int(offset));
 }
 
-static int ffi_return_type_promotes(ffi_type *f)
+static int ffi_return_type_adjustment(ffi_type *f)
 {
-  /* libffi promotes integer return types that are smaller than a word */
+#ifdef ARCH_BIG_ENDIAN
+  /* An adjustment is needed (on bigendian systems) for integer types
+     less than the size of a word */
   if (f->size < sizeof(ffi_arg)) {
     switch (f->type) {
     case FFI_TYPE_INT:
@@ -270,21 +272,10 @@ static int ffi_return_type_promotes(ffi_
     case FFI_TYPE_SINT32:
     case FFI_TYPE_UINT64:
     case FFI_TYPE_SINT64:
-      return 1;
+      return sizeof(ffi_arg) - f->size;
     default: break;
     }
   }
-  return 0;
-}
-
-static int ffi_return_type_adjustment(ffi_type *f)
-{
-#ifdef ARCH_BIG_ENDIAN
-  /* An adjustment is needed (on bigendian systems) for integer types
-     less than the size of a word */
-  if (ffi_return_type_promotes(f)) {
-    return sizeof(ffi_arg) - f->size;
-  }
 #endif
   return 0;
 }
@@ -471,13 +462,51 @@ static void callback_handler_with_lock(f
   /* now store the return value */
   assert (Tag_val(boxedfn) == Done);
 
-  if (ffi_return_type_promotes(cif->rtype)) {
-    *(ffi_arg *)ret = 0;     
-  }
-
-  argptr = CTYPES_FROM_PTR(ret + ffi_return_type_adjustment(cif->rtype));
+  argptr = CTYPES_FROM_PTR(ret);
   caml_callback(Field(boxedfn, 0), argptr);
 
+  /* workaround for libffi api: small integers must be promoted to
+   * full word size (sign/zero extended) */
+  if (cif->rtype->size < sizeof(ffi_arg)) {
+    int do_nothing = 0;
+    ffi_arg x;
+    switch (cif->rtype->type) {
+    case FFI_TYPE_INT:
+      x = *(int*)ret;
+      break;
+    case FFI_TYPE_UINT8:
+      x = *(uint8_t*)ret;
+      break;
+    case FFI_TYPE_SINT8:
+      x = *(int8_t*)ret;
+      break;
+    case FFI_TYPE_UINT16:
+      x = *(uint16_t*)ret;
+      break;
+    case FFI_TYPE_SINT16:
+      x = *(int16_t*)ret;
+      break;
+    case FFI_TYPE_UINT32:
+      x = *(uint32_t*)ret;
+      break;
+    case FFI_TYPE_SINT32:
+      x = *(int32_t*)ret;
+      break;
+    case FFI_TYPE_UINT64:
+      x = *(uint64_t*)ret;
+      break;
+    case FFI_TYPE_SINT64:
+      x = *(int64_t*)ret;
+      break;
+    default:
+      do_nothing = 1;
+      break;
+    }
+    if ( do_nothing == 0 ) {
+      *(ffi_arg*)ret = x;
+    }
+  }
+
   CAMLreturn0;
 }
 

Reply via email to