PMunch/futhark

Opir/Futhark fails to import code that uses `__int128`

beef331 opened this issue · 3 comments

Attempting to wrap wasmedge for instance fails due to hitting __int128. The following is what I'm using if it helps. In this API one does not directly touch the data at __int128 so any allocation that matches the size should result in usable code.

import futhark
import std/strutils

proc removeWasmEdge(name, kind, partof: string): string =
  const prefix = "WasmEdge_"
  result =
    if name.startsWith(prefix):
      name[prefix.len..name.high]
    else:
      name
  case kind
  of "const", "typedef":
    discard
  else:
    result[0] = result[0].toLowerAscii

importc:
  sysPath "/usr/lib/clang/13.0.1/include"
  path "/home/jason/.wasmedge/include/"
  renameCallback removeWasmEdge
  "wasmedge/wasmedge.h"

Well importing int128 now works but there is another related issue

typedef struct WasmEdge_Value {
  uint128_t Value;                              
  enum WasmEdge_ValType Type;                              
} WasmEdge_Value;

sizeof(WasmEdge_Value) on C is 32 but inside Nim it's 24.

The following type definitions resolve the issue.

type
  uInt128t* {.importc: "unsigned __int128".} = object
    do_not_use1, do_not_use2: uint64
  int128t* {.importc: "__int128".} = object
    do_not_use1, do_not_use2: uint64

Hmm, this is a bit weird. So the uint128t and uint128t should be the same size as what Futhark spits out for those, 16 bytes. I believe the issue might be with alignment and padding. Probably the C-compiler does something different for int128t than for a struct of the same size.

That does indeed seem to be the issue. The following test C code:

#include <stdint.h>
#include <stdio.h>

typedef struct {
    int64_t a;
    int64_t b;
} fake;

typedef struct {
    __int128 f1;
    int64_t f2;
} withreal;

typedef struct {
    fake f1;
    int64_t f2;
} withfake;

int main() {
    printf("__int128 %d\n", sizeof(__int128));
    printf("struct %d\n", sizeof(fake));
    printf("withreal %d\n", sizeof(withreal));
    printf("withfake %d\n", sizeof(withfake));
}

outputs this:

__int128 16
struct 16
withreal 32
withfake 24

Not entirely sure how to fix that, or if it is even fixable in a trivial way. But as you say Futhark allows you to define you own type definitions for edge cases like this.