Skip to content

Commit

Permalink
Merge pull request #55 from dra27/unaligned-128
Browse files Browse the repository at this point in the history
Always store OCaml representation as a struct
  • Loading branch information
rgrinberg authored Oct 28, 2020
2 parents 8bfd6e0 + cc56911 commit f14fe83
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Fix sign extensions (#49, @rixed)
* `Long_val` returns `intnat`, previously `long` was used (#53, @dra27)
* Reduce size of marshalled custom values on 4.08+ (#54, @dra27)
* Store 128-bit ints as structs to prevent unaligned access (#55, @dra27)

## New features:

Expand Down
15 changes: 14 additions & 1 deletion lib/int128.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@
#define OCAML_INT128_H

#if defined(__SIZEOF_INT128__)

#define HAVE_INT128
typedef __int128_t int128;
typedef struct { uint64_t low; int64_t high; } int128_ocaml;

inline __int128_t get_int128(value v)
{
int128_ocaml *i = (int128_ocaml *)Data_custom_val(v);
return ((__int128_t)i->high << 64 | i->low);
}

#define Int128_val(v) get_int128(v)

#else

typedef struct { int64_t high; uint64_t low; } int128;
#endif

#define Int128_val(v) (*((int128 *)Data_custom_val(v)))

#endif

CAMLextern value copy_int128(int128 i);

#endif
13 changes: 13 additions & 0 deletions lib/int128_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ struct custom_operations int128_ops = {
#endif
};

#ifdef HAVE_INT128
CAMLprim value
copy_int128(__int128_t i)
{
CAMLparam0();
value res = caml_alloc_custom(&int128_ops, 16, 0, 1);
int128_ocaml *v = (int128_ocaml *)Data_custom_val(res);
v->high = (int64_t)(i >> 64);
v->low = (uint64_t)i;
CAMLreturn (res);
}
#else
CAMLprim value
copy_int128(int128 i)
{
Expand All @@ -155,6 +167,7 @@ copy_int128(int128 i)
Int128_val(res) = i;
CAMLreturn (res);
}
#endif

CAMLprim value
int128_add(value v1, value v2)
Expand Down
16 changes: 14 additions & 2 deletions lib/uint128.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@
#define OCAML_UINT128_H

#if defined(__SIZEOF_INT128__)

#define HAVE_UINT128
typedef __uint128_t uint128;
typedef struct { uint64_t low; uint64_t high; } uint128_ocaml;

inline __uint128_t get_uint128(value v)
{
uint128_ocaml *i = (uint128_ocaml *)Data_custom_val(v);
return ((__uint128_t)i->high << 64 | i->low);
}

#define Uint128_val(v) get_uint128(v)

#else

typedef struct { uint64_t high; uint64_t low; } uint128;
#endif

#define Uint128_val(v) (*((uint128 *)Data_custom_val(v)))

#endif

CAMLextern value copy_uint128(uint128 i);
CAMLextern value suint128_add(value v1, value v2, CAMLprim value (*)(uint128));
CAMLextern value suint128_sub(value v1, value v2, CAMLprim value (*)(uint128));
Expand All @@ -20,4 +33,3 @@ CAMLextern value suint128_xor(value v1, value v2, CAMLprim value (*)(uint128));
CAMLextern value suint128_shift_left(value v1, value v2, CAMLprim value (*)(uint128));

#endif

13 changes: 13 additions & 0 deletions lib/uint128_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,18 @@ struct custom_operations uint128_ops = {
#endif
};

#ifdef HAVE_UINT128
CAMLprim value
copy_uint128(__uint128_t i)
{
CAMLparam0();
value res = caml_alloc_custom(&uint128_ops, 16, 0, 1);
uint128_ocaml *v = (uint128_ocaml *)Data_custom_val(res);
v->high = (uint64_t)(i >> 64);
v->low = (uint64_t)i;
CAMLreturn (res);
}
#else
CAMLprim value
copy_uint128(uint128 i)
{
Expand All @@ -197,6 +209,7 @@ copy_uint128(uint128 i)
Uint128_val(res) = i;
CAMLreturn (res);
}
#endif

CAMLprim value
suint128_add(value v1, value v2, CAMLprim value (*copy)(uint128))
Expand Down

0 comments on commit f14fe83

Please sign in to comment.