| Anonymous | Login | Signup for a new account | 2013-05-20 15:36 CEST | ![]() |
| Main | My View | View Issues | Change Log | Roadmap |
| View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||||||
| ID | Project | Category | View Status | Date Submitted | Last Update | ||||||
| 0005771 | OCaml | OCaml backend (code generation) | public | 2012-10-02 16:02 | 2012-12-19 16:44 | ||||||
| Reporter | chambart | ||||||||||
| Assigned To | lefessan | ||||||||||
| Priority | normal | Severity | feature | Reproducibility | always | ||||||
| Status | confirmed | Resolution | fixed | ||||||||
| Platform | OS | OS Version | |||||||||
| Product Version | |||||||||||
| Target Version | Fixed in Version | 4.01.0+dev | |||||||||
| Summary | 0005771: [patch] add primitives for directly reading 2, 4 or 8 bytes in strings and char bigarrays | ||||||||||
| Description | This patch provides primitives to improve speed of code reading a lot of values from network/files. When those are implemented using C stubs, quite a lot of time is spent in the calls. the provided primitives are: type bigstring = (char, int8_unsigned_elt, c_layout) Array1.t external caml_bigstring_get_16 : bigstring -> int -> int = "%caml_bigstring_get16" external caml_bigstring_get_32 : bigstring -> int -> int32 = "%caml_bigstring_get32" external caml_bigstring_get_64 : bigstring -> int -> int64 = "%caml_bigstring_get64" external caml_bigstring_set_16 : bigstring -> int -> int -> unit = "%caml_bigstring_set16" external caml_bigstring_set_32 : bigstring -> int -> int32 -> unit = "%caml_bigstring_set32" external caml_bigstring_set_64 : bigstring -> int -> int64 -> unit = "%caml_bigstring_set64" and the equivalent ones on strings. external caml_string_get_16 : string -> int -> int = "%caml_string_get16" external caml_string_get_32 : string -> int -> int32 = "%caml_string_get32" external caml_string_get_64 : string -> int -> int64 = "%caml_string_get64" external caml_string_set_16 : string -> int -> int -> unit = "%caml_string_set16" external caml_string_set_32 : string -> int -> int32 -> unit = "%caml_string_set32" external caml_string_set_64 : string -> int -> int64 -> unit = "%caml_string_set64" Unsafe versions of the primitives also exist. | ||||||||||
| Additional Information | Those primitives allow loading values that are not alligned. On architectures that does not allow unaligned access this is implemented by loading one byte at a time. It is allowed on x86 and x86-64, but for the other architectures I made the safe guess that it is forbiden. Is it effectively the case on power processors ? On a future version of the patch I can implement a more efficient unaligned load that requires only 2 loads and some shifts. | ||||||||||
| Tags | No tags attached. | ||||||||||
| Attached Files | From f4c4efeff1adbec5167d644f600830f92001e932 Mon Sep 17 00:00:00 2001
From: Pierre Chambart <pierre.chambart@ocamlpro.org>
Date: Mon, 24 Sep 2012 18:40:34 +0200
Subject: [PATCH 1/7] Add primitives to load and write 2, 4, and 8 bytes to
char bigarrays and strings
---
asmcomp/amd64/arch.ml | 2 +
asmcomp/arm/arch.ml | 2 +
asmcomp/cmmgen.ml | 263 ++++++++++++++++++++
asmcomp/i386/arch.ml | 2 +
asmcomp/power/arch.ml | 2 +
asmcomp/sparc/arch.ml | 2 +
bytecomp/bytegen.ml | 12 +
bytecomp/lambda.ml | 15 ++
bytecomp/lambda.mli | 15 ++
bytecomp/printlambda.ml | 36 +++
bytecomp/translcore.ml | 24 ++
byterun/str.c | 142 +++++++++++
otherlibs/bigarray/bigarray_stubs.c | 149 +++++++++++
testsuite/tests/prim-bigstring/Makefile | 5 +
testsuite/tests/prim-bigstring/bigstring_access.ml | 86 +++++++
.../prim-bigstring/bigstring_access.reference | 6 +
testsuite/tests/prim-bigstring/string_access.ml | 79 ++++++
.../tests/prim-bigstring/string_access.reference | 6 +
18 files changed, 848 insertions(+)
create mode 100644 testsuite/tests/prim-bigstring/Makefile
create mode 100644 testsuite/tests/prim-bigstring/bigstring_access.ml
create mode 100644 testsuite/tests/prim-bigstring/bigstring_access.reference
create mode 100644 testsuite/tests/prim-bigstring/string_access.ml
create mode 100644 testsuite/tests/prim-bigstring/string_access.reference
diff --git a/asmcomp/amd64/arch.ml b/asmcomp/amd64/arch.ml
index 6d66129..43d513a 100644
--- a/asmcomp/amd64/arch.ml
+++ b/asmcomp/amd64/arch.ml
@@ -49,6 +49,8 @@ let size_addr = 8
let size_int = 8
let size_float = 8
+let allow_unaligned_access = true
+
(* Behavior of division *)
let division_crashes_on_overflow = true
diff --git a/asmcomp/arm/arch.ml b/asmcomp/arm/arch.ml
index a12d6d3..fd46f07 100644
--- a/asmcomp/arm/arch.ml
+++ b/asmcomp/arm/arch.ml
@@ -132,6 +132,8 @@ let size_addr = 4
let size_int = 4
let size_float = 8
+let allow_unaligned_access = false
+
(* Behavior of division *)
let division_crashes_on_overflow = false
diff --git a/asmcomp/cmmgen.ml b/asmcomp/cmmgen.ml
index 31272f6..0e9da63 100644
--- a/asmcomp/cmmgen.ml
+++ b/asmcomp/cmmgen.ml
@@ -651,6 +651,158 @@ let bigarray_set unsafe elt_kind layout b args newval dbg =
Cop(Cstore (bigarray_word_kind elt_kind),
[bigarray_indexing unsafe elt_kind layout b args dbg; newval]))
+let unaligned_load_16 ptr idx =
+ if Arch.allow_unaligned_access
+ then Cop(Cload Sixteen_unsigned, [add_int ptr idx])
+ else
+ let v1 = Cop(Cload Byte_unsigned, [add_int ptr idx]) in
+ let v2 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 1)]) in
+ let b1, b2 = if Arch.big_endian then v1, v2 else v2, v1 in
+ Cop(Cor, [lsl_int b1 (Cconst_int 8); b2])
+
+let unaligned_set_16 ptr idx newval =
+ if Arch.allow_unaligned_access
+ then Cop(Cstore Sixteen_unsigned, [add_int ptr idx; newval])
+ else
+ let v1 = Cop(Cand, [Cop(Clsr, [newval; Cconst_int 8]); Cconst_int 0xFF]) in
+ let v2 = Cop(Cand, [newval; Cconst_int 0xFF]) in
+ let b1, b2 = if Arch.big_endian then v1, v2 else v2, v1 in
+ Csequence(
+ Cop(Cstore Byte_unsigned, [add_int ptr idx; b1]),
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 1); b2]))
+
+let unaligned_load_32 ptr idx =
+ if Arch.allow_unaligned_access
+ then Cop(Cload Thirtytwo_unsigned, [add_int ptr idx])
+ else
+ let v1 = Cop(Cload Byte_unsigned, [add_int ptr idx]) in
+ let v2 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 1)]) in
+ let v3 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 2)]) in
+ let v4 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 3)]) in
+ let b1, b2, b3, b4 =
+ if Arch.big_endian
+ then v1, v2, v3, v4
+ else v4, v3, v2, v1 in
+ Cop(Cor,
+ [Cop(Cor, [lsl_int b1 (Cconst_int 24); lsl_int b2 (Cconst_int 16)]);
+ Cop(Cor, [lsl_int b3 (Cconst_int 8); b4])])
+
+let unaligned_set_32 ptr idx newval =
+ if Arch.allow_unaligned_access
+ then Cop(Cstore Thirtytwo_unsigned, [add_int ptr idx; newval])
+ else
+ let v1 =
+ Cop(Cand, [Cop(Clsr, [newval; Cconst_int 24]); Cconst_int 0xFF]) in
+ let v2 =
+ Cop(Cand, [Cop(Clsr, [newval; Cconst_int 16]); Cconst_int 0xFF]) in
+ let v3 =
+ Cop(Cand, [Cop(Clsr, [newval; Cconst_int 8]); Cconst_int 0xFF]) in
+ let v4 = Cop(Cand, [newval; Cconst_int 0xFF]) in
+ let b1, b2, b3, b4 =
+ if Arch.big_endian
+ then v1, v2, v3, v4
+ else v4, v3, v2, v1 in
+ Csequence(
+ Csequence(
+ Cop(Cstore Byte_unsigned, [add_int ptr idx; b1]),
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 1); b2])),
+ Csequence(
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 2); b3]),
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 3); b4])))
+
+let unaligned_load_64 ptr idx =
+ assert(size_int = 8);
+ if Arch.allow_unaligned_access
+ then Cop(Cload Word, [add_int ptr idx])
+ else
+ let v1 = Cop(Cload Byte_unsigned, [add_int ptr idx]) in
+ let v2 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 1)]) in
+ let v3 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 2)]) in
+ let v4 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 3)]) in
+ let v5 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 4)]) in
+ let v6 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 5)]) in
+ let v7 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 6)]) in
+ let v8 = Cop(Cload Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 7)]) in
+ let b1, b2, b3, b4, b5, b6, b7, b8 =
+ if Arch.big_endian
+ then v1, v2, v3, v4, v5, v6, v7, v8
+ else v8, v7, v6, v5, v4, v3, v2, v1 in
+ Cop(Cor,
+ [Cop(Cor,
+ [Cop(Cor, [lsl_int b1 (Cconst_int (8*7));
+ lsl_int b2 (Cconst_int (8*6))]);
+ Cop(Cor, [lsl_int b3 (Cconst_int (8*5));
+ lsl_int b4 (Cconst_int (8*4))])]);
+ Cop(Cor,
+ [Cop(Cor, [lsl_int b5 (Cconst_int (8*3));
+ lsl_int b6 (Cconst_int (8*2))]);
+ Cop(Cor, [lsl_int b7 (Cconst_int 8);
+ b8])])])
+
+let unaligned_set_64 ptr idx newval =
+ assert(size_int = 8);
+ if Arch.allow_unaligned_access
+ then Cop(Cstore Word, [add_int ptr idx; newval])
+ else
+ let v1 =
+ Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*7)]); Cconst_int 0xFF]) in
+ let v2 =
+ Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*6)]); Cconst_int 0xFF]) in
+ let v3 =
+ Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*5)]); Cconst_int 0xFF]) in
+ let v4 =
+ Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*4)]); Cconst_int 0xFF]) in
+ let v5 =
+ Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*3)]); Cconst_int 0xFF]) in
+ let v6 =
+ Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*2)]); Cconst_int 0xFF]) in
+ let v7 = Cop(Cand, [Cop(Clsr, [newval; Cconst_int 8]); Cconst_int 0xFF]) in
+ let v8 = Cop(Cand, [newval; Cconst_int 0xFF]) in
+ let b1, b2, b3, b4, b5, b6, b7, b8 =
+ if Arch.big_endian
+ then v1, v2, v3, v4, v5, v6, v7, v8
+ else v8, v7, v6, v5, v4, v3, v2, v1 in
+ Csequence(
+ Csequence(
+ Csequence(
+ Cop(Cstore Byte_unsigned, [add_int ptr idx; b1]),
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 1); b2])),
+ Csequence(
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 2); b3]),
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 3); b4]))),
+ Csequence(
+ Csequence(
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 4); b5]),
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 5); b6])),
+ Csequence(
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 6); b7]),
+ Cop(Cstore Byte_unsigned,
+ [add_int (add_int ptr idx) (Cconst_int 7); b8]))))
+
+let check_bound unsafe dbg a1 a2 k =
+ if unsafe then k else Csequence(make_checkbound dbg [a1;a2], k)
+
(* Simplification of some primitives into C calls *)
let default_prim name =
@@ -688,6 +840,10 @@ let simplif_primitive_32bits = function
Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
| Pbigarrayset(unsafe, n, Pbigarray_int64, layout) ->
Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
+ | Pstring_load_64(_) -> Pccall (default_prim "caml_string_get64")
+ | Pstring_set_64(_) -> Pccall (default_prim "caml_string_set64")
+ | Pbigstring_load_64(_) -> Pccall (default_prim "caml_ba_uint8_get64")
+ | Pbigstring_set_64(_) -> Pccall (default_prim "caml_ba_uint8_set64")
| p -> p
let simplif_primitive p =
@@ -800,6 +956,10 @@ let is_unboxed_number = function
| Pbigarrayref(_, _, Pbigarray_int32, _) -> Boxed_integer Pint32
| Pbigarrayref(_, _, Pbigarray_int64, _) -> Boxed_integer Pint64
| Pbigarrayref(_, _, Pbigarray_native_int, _) -> Boxed_integer Pnativeint
+ | Pstring_load_32(_) -> Boxed_integer Pint32
+ | Pstring_load_64(_) -> Boxed_integer Pint64
+ | Pbigstring_load_32(_) -> Boxed_integer Pint32
+ | Pbigstring_load_64(_) -> Boxed_integer Pint64
| _ -> No_unboxing
end
| _ -> No_unboxing
@@ -1252,6 +1412,54 @@ and transl_prim_2 p arg1 arg2 dbg =
make_checkbound dbg [string_length str; idx],
Cop(Cload Byte_unsigned, [add_int str idx])))))
+ | Pstring_load_16(unsafe) ->
+ tag_int
+ (bind "str" (transl arg1) (fun str ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 1)) idx
+ (unaligned_load_16 str idx))))
+
+ | Pbigstring_load_16(unsafe) ->
+ tag_int
+ (bind "ba" (transl arg1) (fun ba ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
+ check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+ (Cconst_int 1)) idx
+ (unaligned_load_16 ba_data idx)))))
+
+ | Pstring_load_32(unsafe) ->
+ box_int Pint32
+ (bind "str" (transl arg1) (fun str ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 3)) idx
+ (unaligned_load_32 str idx))))
+
+ | Pbigstring_load_32(unsafe) ->
+ box_int Pint32
+ (bind "ba" (transl arg1) (fun ba ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
+ check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+ (Cconst_int 3)) idx
+ (unaligned_load_32 ba_data idx)))))
+
+ | Pstring_load_64(unsafe) ->
+ box_int Pint64
+ (bind "str" (transl arg1) (fun str ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 7)) idx
+ (unaligned_load_64 str idx))))
+
+ | Pbigstring_load_64(unsafe) ->
+ box_int Pint64
+ (bind "ba" (transl arg1) (fun ba ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
+ check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+ (Cconst_int 7)) idx
+ (unaligned_load_64 ba_data idx)))))
+
(* Array operations *)
| Parrayrefu kind ->
begin match kind with
@@ -1421,6 +1629,61 @@ and transl_prim_3 p arg1 arg2 arg3 dbg =
Csequence(make_checkbound dbg [float_array_length(header arr);idx],
float_array_set arr idx newval))))
end)
+
+ | Pstring_set_16(unsafe) ->
+ return_unit
+ (bind "str" (transl arg1) (fun str ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ bind "newval" (untag_int (transl arg3)) (fun newval ->
+ check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 1)) idx
+ (unaligned_set_16 str idx newval)))))
+
+ | Pbigstring_set_16(unsafe) ->
+ return_unit
+ (bind "ba" (transl arg1) (fun ba ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ bind "newval" (untag_int (transl arg3)) (fun newval ->
+ bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
+ check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+ (Cconst_int 1)) idx
+ (unaligned_set_16 ba_data idx newval))))))
+
+ | Pstring_set_32(unsafe) ->
+ return_unit
+ (bind "str" (transl arg1) (fun str ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ bind "newval" (transl_unbox_int Pint32 arg3) (fun newval ->
+ check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 3)) idx
+ (unaligned_set_32 str idx newval)))))
+
+ | Pbigstring_set_32(unsafe) ->
+ return_unit
+ (bind "ba" (transl arg1) (fun ba ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ bind "newval" (transl_unbox_int Pint32 arg3) (fun newval ->
+ bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
+ check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+ (Cconst_int 3)) idx
+ (unaligned_set_32 ba_data idx newval))))))
+
+ | Pstring_set_64(unsafe) ->
+ return_unit
+ (bind "str" (transl arg1) (fun str ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ bind "newval" (transl_unbox_int Pint64 arg3) (fun newval ->
+ check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 7)) idx
+ (unaligned_set_64 str idx newval)))))
+
+ | Pbigstring_set_64(unsafe) ->
+ return_unit
+ (bind "ba" (transl arg1) (fun ba ->
+ bind "index" (untag_int (transl arg2)) (fun idx ->
+ bind "newval" (transl_unbox_int Pint64 arg3) (fun newval ->
+ bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
+ check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+ (Cconst_int 7)) idx
+ (unaligned_set_64 ba_data idx newval))))))
+
| _ ->
fatal_error "Cmmgen.transl_prim_3"
diff --git a/asmcomp/i386/arch.ml b/asmcomp/i386/arch.ml
index 58560fd..d2f9fd6 100644
--- a/asmcomp/i386/arch.ml
+++ b/asmcomp/i386/arch.ml
@@ -56,6 +56,8 @@ let size_addr = 4
let size_int = 4
let size_float = 8
+let allow_unaligned_access = true
+
(* Behavior of division *)
let division_crashes_on_overflow = true
diff --git a/asmcomp/power/arch.ml b/asmcomp/power/arch.ml
index d547df2..4e31a8c 100644
--- a/asmcomp/power/arch.ml
+++ b/asmcomp/power/arch.ml
@@ -44,6 +44,8 @@ let size_addr = if ppc64 then 8 else 4
let size_int = size_addr
let size_float = 8
+let allow_unaligned_access = false
+
(* Behavior of division *)
let division_crashes_on_overflow = true
diff --git a/asmcomp/sparc/arch.ml b/asmcomp/sparc/arch.ml
index 78725b5..f5c0693 100644
--- a/asmcomp/sparc/arch.ml
+++ b/asmcomp/sparc/arch.ml
@@ -44,6 +44,8 @@ let size_addr = 4
let size_int = 4
let size_float = 8
+let allow_unaligned_access = false
+
(* Behavior of division *)
let division_crashes_on_overflow = false
diff --git a/bytecomp/bytegen.ml b/bytecomp/bytegen.ml
index ec528f9..a73151a 100644
--- a/bytecomp/bytegen.ml
+++ b/bytecomp/bytegen.ml
@@ -330,6 +330,12 @@ let comp_primitive p args =
| Pstringsets -> Kccall("caml_string_set", 3)
| Pstringrefu -> Kgetstringchar
| Pstringsetu -> Ksetstringchar
+ | Pstring_load_16(_) -> Kccall("caml_string_get16", 2)
+ | Pstring_load_32(_) -> Kccall("caml_string_get32", 2)
+ | Pstring_load_64(_) -> Kccall("caml_string_get64", 2)
+ | Pstring_set_16(_) -> Kccall("caml_string_set16", 3)
+ | Pstring_set_32(_) -> Kccall("caml_string_set32", 3)
+ | Pstring_set_64(_) -> Kccall("caml_string_set64", 3)
| Parraylength kind -> Kvectlength
| Parrayrefs Pgenarray -> Kccall("caml_array_get", 2)
| Parrayrefs Pfloatarray -> Kccall("caml_array_get_float", 2)
@@ -375,6 +381,12 @@ let comp_primitive p args =
| Pbigarrayref(_, n, _, _) -> Kccall("caml_ba_get_" ^ string_of_int n, n + 1)
| Pbigarrayset(_, n, _, _) -> Kccall("caml_ba_set_" ^ string_of_int n, n + 2)
| Pbigarraydim(n) -> Kccall("caml_ba_dim_" ^ string_of_int n, 1)
+ | Pbigstring_load_16(_) -> Kccall("caml_ba_uint8_get16", 2)
+ | Pbigstring_load_32(_) -> Kccall("caml_ba_uint8_get32", 2)
+ | Pbigstring_load_64(_) -> Kccall("caml_ba_uint8_get64", 2)
+ | Pbigstring_set_16(_) -> Kccall("caml_ba_uint8_set16", 3)
+ | Pbigstring_set_32(_) -> Kccall("caml_ba_uint8_set32", 3)
+ | Pbigstring_set_64(_) -> Kccall("caml_ba_uint8_set64", 3)
| _ -> fatal_error "Bytegen.comp_primitive"
let is_immed n = immed_min <= n && n <= immed_max
diff --git a/bytecomp/lambda.ml b/bytecomp/lambda.ml
index e2f9e06..1239648 100644
--- a/bytecomp/lambda.ml
+++ b/bytecomp/lambda.ml
@@ -86,6 +86,21 @@ type primitive =
| Pbigarrayset of bool * int * bigarray_kind * bigarray_layout
(* size of the nth dimension of a big array *)
| Pbigarraydim of int
+ (* load/set 16,32,64 bits from a string: (unsafe)*)
+ | Pstring_load_16 of bool
+ | Pstring_load_32 of bool
+ | Pstring_load_64 of bool
+ | Pstring_set_16 of bool
+ | Pstring_set_32 of bool
+ | Pstring_set_64 of bool
+ (* load/set 16,32,64 bits from a
+ (char, int8_unsigned_elt, c_layout) Bigarray.Array1.t : (unsafe) *)
+ | Pbigstring_load_16 of bool
+ | Pbigstring_load_32 of bool
+ | Pbigstring_load_64 of bool
+ | Pbigstring_set_16 of bool
+ | Pbigstring_set_32 of bool
+ | Pbigstring_set_64 of bool
and comparison =
Ceq | Cneq | Clt | Cgt | Cle | Cge
diff --git a/bytecomp/lambda.mli b/bytecomp/lambda.mli
index af2a9e6..277e373 100644
--- a/bytecomp/lambda.mli
+++ b/bytecomp/lambda.mli
@@ -86,6 +86,21 @@ type primitive =
| Pbigarrayset of bool * int * bigarray_kind * bigarray_layout
(* size of the nth dimension of a big array *)
| Pbigarraydim of int
+ (* load/set 16,32,64 bits from a string: (unsafe)*)
+ | Pstring_load_16 of bool
+ | Pstring_load_32 of bool
+ | Pstring_load_64 of bool
+ | Pstring_set_16 of bool
+ | Pstring_set_32 of bool
+ | Pstring_set_64 of bool
+ (* load/set 16,32,64 bits from a
+ (char, int8_unsigned_elt, c_layout) Bigarray.Array1.t : (unsafe) *)
+ | Pbigstring_load_16 of bool
+ | Pbigstring_load_32 of bool
+ | Pbigstring_load_64 of bool
+ | Pbigstring_set_16 of bool
+ | Pbigstring_set_32 of bool
+ | Pbigstring_set_64 of bool
and comparison =
Ceq | Cneq | Clt | Cgt | Cle | Cge
diff --git a/bytecomp/printlambda.ml b/bytecomp/printlambda.ml
index e6d8430..185d22a 100644
--- a/bytecomp/printlambda.ml
+++ b/bytecomp/printlambda.ml
@@ -183,6 +183,42 @@ let primitive ppf = function
| Pbigarrayset(unsafe, n, kind, layout) ->
print_bigarray "set" unsafe kind ppf layout
| Pbigarraydim(n) -> fprintf ppf "Bigarray.dim_%i" n
+ | Pstring_load_16(unsafe) ->
+ if unsafe then fprintf ppf "string.unsafe_get16"
+ else fprintf ppf "string.get16"
+ | Pstring_load_32(unsafe) ->
+ if unsafe then fprintf ppf "string.unsafe_get32"
+ else fprintf ppf "string.get32"
+ | Pstring_load_64(unsafe) ->
+ if unsafe then fprintf ppf "string.unsafe_get64"
+ else fprintf ppf "string.get64"
+ | Pstring_set_16(unsafe) ->
+ if unsafe then fprintf ppf "string.unsafe_set16"
+ else fprintf ppf "string.set16"
+ | Pstring_set_32(unsafe) ->
+ if unsafe then fprintf ppf "string.unsafe_set32"
+ else fprintf ppf "string.set32"
+ | Pstring_set_64(unsafe) ->
+ if unsafe then fprintf ppf "string.unsafe_set64"
+ else fprintf ppf "string.set64"
+ | Pbigstring_load_16(unsafe) ->
+ if unsafe then fprintf ppf "bigarray.array1.unsafe_get16"
+ else fprintf ppf "bigarray.array1.get16"
+ | Pbigstring_load_32(unsafe) ->
+ if unsafe then fprintf ppf "bigarray.array1.unsafe_get32"
+ else fprintf ppf "bigarray.array1.get32"
+ | Pbigstring_load_64(unsafe) ->
+ if unsafe then fprintf ppf "bigarray.array1.unsafe_get64"
+ else fprintf ppf "bigarray.array1.get64"
+ | Pbigstring_set_16(unsafe) ->
+ if unsafe then fprintf ppf "bigarray.array1.unsafe_set16"
+ else fprintf ppf "bigarray.array1.set16"
+ | Pbigstring_set_32(unsafe) ->
+ if unsafe then fprintf ppf "bigarray.array1.unsafe_set32"
+ else fprintf ppf "bigarray.array1.set32"
+ | Pbigstring_set_64(unsafe) ->
+ if unsafe then fprintf ppf "bigarray.array1.unsafe_set64"
+ else fprintf ppf "bigarray.array1.set64"
let rec lam ppf = function
| Lvar id ->
diff --git a/bytecomp/translcore.ml b/bytecomp/translcore.ml
index 9c2f364..c4d22a1 100644
--- a/bytecomp/translcore.ml
+++ b/bytecomp/translcore.ml
@@ -276,6 +276,30 @@ let primitives_table = create_hashtable 57 [
"%caml_ba_dim_1", Pbigarraydim(1);
"%caml_ba_dim_2", Pbigarraydim(2);
"%caml_ba_dim_3", Pbigarraydim(3);
+ "%caml_string_get16", Pstring_load_16(false);
+ "%caml_string_get16u", Pstring_load_16(true);
+ "%caml_string_get32", Pstring_load_32(false);
+ "%caml_string_get32u", Pstring_load_32(true);
+ "%caml_string_get64", Pstring_load_64(false);
+ "%caml_string_get64u", Pstring_load_64(true);
+ "%caml_string_set16", Pstring_set_16(false);
+ "%caml_string_set16u", Pstring_set_16(true);
+ "%caml_string_set32", Pstring_set_32(false);
+ "%caml_string_set32u", Pstring_set_32(true);
+ "%caml_string_set64", Pstring_set_64(false);
+ "%caml_string_set64u", Pstring_set_64(true);
+ "%caml_bigstring_get16", Pbigstring_load_16(false);
+ "%caml_bigstring_get16u", Pbigstring_load_16(true);
+ "%caml_bigstring_get32", Pbigstring_load_32(false);
+ "%caml_bigstring_get32u", Pbigstring_load_32(true);
+ "%caml_bigstring_get64", Pbigstring_load_64(false);
+ "%caml_bigstring_get64u", Pbigstring_load_64(true);
+ "%caml_bigstring_set16", Pbigstring_set_16(false);
+ "%caml_bigstring_set16u", Pbigstring_set_16(true);
+ "%caml_bigstring_set32", Pbigstring_set_32(false);
+ "%caml_bigstring_set32u", Pbigstring_set_32(true);
+ "%caml_bigstring_set64", Pbigstring_set_64(false);
+ "%caml_bigstring_set64u", Pbigstring_set_64(true);
]
let prim_makearray =
diff --git a/byterun/str.c b/byterun/str.c
index 8120a5b..147d13c 100644
--- a/byterun/str.c
+++ b/byterun/str.c
@@ -63,6 +63,148 @@ CAMLprim value caml_string_set(value str, value index, value newval)
return Val_unit;
}
+CAMLprim value caml_string_get16(value str, value index)
+{
+ intnat idx = Long_val(index);
+ if (idx < 0 || idx >= caml_string_length(str) - 1) caml_array_bound_error();
+ intnat res;
+ unsigned char b1 = Byte_u(str, idx);
+ unsigned char b2 = Byte_u(str, idx + 1);
+#ifdef ARCH_BIG_ENDIAN
+ res = b1 << 8 | b2;
+#else
+ res = b2 << 8 | b1;
+#endif
+ return Val_int(res);
+}
+
+CAMLprim value caml_string_get32(value str, value index)
+{
+ intnat idx = Long_val(index);
+ if (idx < 0 || idx >= caml_string_length(str) - 3) caml_array_bound_error();
+ intnat res;
+ unsigned char b1 = Byte_u(str, idx);
+ unsigned char b2 = Byte_u(str, idx + 1);
+ unsigned char b3 = Byte_u(str, idx + 2);
+ unsigned char b4 = Byte_u(str, idx + 3);
+#ifdef ARCH_BIG_ENDIAN
+ res = b1 << 24 | b2 << 16 | b3 << 8 | b4;
+#else
+ res = b4 << 24 | b3 << 16 | b2 << 8 | b1;
+#endif
+ return caml_copy_int32(res);
+}
+
+#ifdef ARCH_INT64_TYPE
+#include "int64_native.h"
+#else
+#include "int64_emul.h"
+#endif
+
+CAMLprim value caml_string_get64(value str, value index)
+{
+ intnat idx = Long_val(index);
+ if (idx < 0 || idx >= caml_string_length(str) - 7) caml_array_bound_error();
+ uint32 reshi;
+ uint32 reslo;
+ unsigned char b1 = Byte_u(str, idx);
+ unsigned char b2 = Byte_u(str, idx + 1);
+ unsigned char b3 = Byte_u(str, idx + 2);
+ unsigned char b4 = Byte_u(str, idx + 3);
+ unsigned char b5 = Byte_u(str, idx + 4);
+ unsigned char b6 = Byte_u(str, idx + 5);
+ unsigned char b7 = Byte_u(str, idx + 6);
+ unsigned char b8 = Byte_u(str, idx + 7);
+#ifdef ARCH_BIG_ENDIAN
+ reshi = b1 << 24 | b2 << 16 | b3 << 8 | b4;
+ reslo = b5 << 24 | b6 << 16 | b7 << 8 | b8;
+#else
+ reshi = b8 << 24 | b7 << 16 | b6 << 8 | b5;
+ reslo = b4 << 24 | b3 << 16 | b2 << 8 | b1;
+#endif
+ return caml_copy_int64(I64_literal(reshi,reslo));
+}
+
+CAMLprim value caml_string_set16(value str, value index, value newval)
+{
+ intnat idx = Long_val(index);
+ if (idx < 0 || idx >= caml_string_length(str) - 1) caml_array_bound_error();
+ unsigned char b1, b2;
+ intnat val = Long_val(newval);
+#ifdef ARCH_BIG_ENDIAN
+ b1 = 0xFF & val >> 8;
+ b2 = 0xFF & val;
+#else
+ b2 = 0xFF & val >> 8;
+ b1 = 0xFF & val;
+#endif
+ Byte_u(str, idx) = b1;
+ Byte_u(str, idx + 1) = b2;
+ return Val_unit;
+}
+
+CAMLprim value caml_string_set32(value str, value index, value newval)
+{
+ intnat idx = Long_val(index);
+ if (idx < 0 || idx >= caml_string_length(str) - 3) caml_array_bound_error();
+ unsigned char b1, b2, b3, b4;
+ intnat val = Int32_val(newval);
+#ifdef ARCH_BIG_ENDIAN
+ b1 = 0xFF & val >> 24;
+ b2 = 0xFF & val >> 16;
+ b3 = 0xFF & val >> 8;
+ b4 = 0xFF & val;
+#else
+ b4 = 0xFF & val >> 24;
+ b3 = 0xFF & val >> 16;
+ b2 = 0xFF & val >> 8;
+ b1 = 0xFF & val;
+#endif
+ Byte_u(str, idx) = b1;
+ Byte_u(str, idx + 1) = b2;
+ Byte_u(str, idx + 2) = b3;
+ Byte_u(str, idx + 3) = b4;
+ return Val_unit;
+}
+
+CAMLprim value caml_string_set64(value str, value index, value newval)
+{
+ intnat idx = Long_val(index);
+ if (idx < 0 || idx >= caml_string_length(str) - 7) caml_array_bound_error();
+ unsigned char b1, b2, b3, b4, b5, b6, b7, b8;
+ int64 val = Int64_val(newval);
+ uint32 lo,hi;
+ I64_split(val,hi,lo);
+#ifdef ARCH_BIG_ENDIAN
+ b1 = 0xFF & hi >> 24;
+ b2 = 0xFF & hi >> 16;
+ b3 = 0xFF & hi >> 8;
+ b4 = 0xFF & hi;
+ b5 = 0xFF & lo >> 24;
+ b6 = 0xFF & lo >> 16;
+ b7 = 0xFF & lo >> 8;
+ b8 = 0xFF & lo;
+#else
+ b8 = 0xFF & hi >> 24;
+ b7 = 0xFF & hi >> 16;
+ b6 = 0xFF & hi >> 8;
+ b5 = 0xFF & hi;
+ b4 = 0xFF & lo >> 24;
+ b3 = 0xFF & lo >> 16;
+ b2 = 0xFF & lo >> 8;
+ b1 = 0xFF & lo;
+#endif
+ Byte_u(str, idx) = b1;
+ Byte_u(str, idx + 1) = b2;
+ Byte_u(str, idx + 2) = b3;
+ Byte_u(str, idx + 3) = b4;
+ Byte_u(str, idx + 4) = b5;
+ Byte_u(str, idx + 5) = b6;
+ Byte_u(str, idx + 6) = b7;
+ Byte_u(str, idx + 7) = b8;
+ return Val_unit;
+}
+
CAMLprim value caml_string_equal(value s1, value s2)
{
mlsize_t sz1, sz2;
diff --git a/otherlibs/bigarray/bigarray_stubs.c b/otherlibs/bigarray/bigarray_stubs.c
index 4af0bfd..95fe12f 100644
--- a/otherlibs/bigarray/bigarray_stubs.c
+++ b/otherlibs/bigarray/bigarray_stubs.c
@@ -346,6 +346,72 @@ CAMLprim value caml_ba_get_generic(value vb, value vind)
return caml_ba_get_N(vb, &Field(vind, 0), Wosize_val(vind));
}
+
+CAMLprim value caml_ba_uint8_get16(value vb, value vind)
+{
+ intnat idx = Long_val(vind);
+ struct caml_ba_array * b = Caml_ba_array_val(vb);
+ if (idx < 0 || idx >= b->dim[0] - 1) caml_array_bound_error();
+ intnat res;
+ unsigned char b1 = ((unsigned char*) b->data)[idx];
+ unsigned char b2 = ((unsigned char*) b->data)[idx+1];
+#ifdef ARCH_BIG_ENDIAN
+ res = b1 << 8 | b2;
+#else
+ res = b2 << 8 | b1;
+#endif
+ return Val_int(res);
+}
+
+CAMLprim value caml_ba_uint8_get32(value vb, value vind)
+{
+ intnat idx = Long_val(vind);
+ struct caml_ba_array * b = Caml_ba_array_val(vb);
+ if (idx < 0 || idx >= b->dim[0] - 3) caml_array_bound_error();
+ intnat res;
+ unsigned char b1 = ((unsigned char*) b->data)[idx];
+ unsigned char b2 = ((unsigned char*) b->data)[idx+1];
+ unsigned char b3 = ((unsigned char*) b->data)[idx+2];
+ unsigned char b4 = ((unsigned char*) b->data)[idx+3];
+#ifdef ARCH_BIG_ENDIAN
+ res = b1 << 24 | b2 << 16 | b3 << 8 | b4;
+#else
+ res = b4 << 24 | b3 << 16 | b2 << 8 | b1;
+#endif
+ return caml_copy_int32(res);
+}
+
+#ifdef ARCH_INT64_TYPE
+#include "int64_native.h"
+#else
+#include "int64_emul.h"
+#endif
+
+CAMLprim value caml_ba_uint8_get64(value vb, value vind)
+{
+ intnat idx = Long_val(vind);
+ struct caml_ba_array * b = Caml_ba_array_val(vb);
+ if (idx < 0 || idx >= b->dim[0] - 7) caml_array_bound_error();
+ uint32 reshi;
+ uint32 reslo;
+ unsigned char b1 = ((unsigned char*) b->data)[idx];
+ unsigned char b2 = ((unsigned char*) b->data)[idx+1];
+ unsigned char b3 = ((unsigned char*) b->data)[idx+2];
+ unsigned char b4 = ((unsigned char*) b->data)[idx+3];
+ unsigned char b5 = ((unsigned char*) b->data)[idx+4];
+ unsigned char b6 = ((unsigned char*) b->data)[idx+5];
+ unsigned char b7 = ((unsigned char*) b->data)[idx+6];
+ unsigned char b8 = ((unsigned char*) b->data)[idx+7];
+#ifdef ARCH_BIG_ENDIAN
+ reshi = b1 << 24 | b2 << 16 | b3 << 8 | b4;
+ reslo = b5 << 24 | b6 << 16 | b7 << 8 | b8;
+#else
+ reshi = b8 << 24 | b7 << 16 | b6 << 8 | b5;
+ reslo = b4 << 24 | b3 << 16 | b2 << 8 | b1;
+#endif
+ return caml_copy_int64(I64_literal(reshi,reslo));
+}
+
/* Generic write to a big array */
static value caml_ba_set_aux(value vb, value * vind, intnat nind, value newval)
@@ -457,6 +523,89 @@ CAMLprim value caml_ba_set_generic(value vb, value vind, value newval)
return caml_ba_set_aux(vb, &Field(vind, 0), Wosize_val(vind), newval);
}
+CAMLprim value caml_ba_uint8_set16(value vb, value vind, value newval)
+{
+ intnat idx = Long_val(vind);
+ struct caml_ba_array * b = Caml_ba_array_val(vb);
+ if (idx < 0 || idx >= b->dim[0] - 1) caml_array_bound_error();
+ unsigned char b1, b2;
+ intnat val = Long_val(newval);
+#ifdef ARCH_BIG_ENDIAN
+ b1 = 0xFF & val >> 8;
+ b2 = 0xFF & val;
+#else
+ b2 = 0xFF & val >> 8;
+ b1 = 0xFF & val;
+#endif
+ ((unsigned char*) b->data)[idx] = b1;
+ ((unsigned char*) b->data)[idx+1] = b2;
+ return Val_unit;
+}
+
+CAMLprim value caml_ba_uint8_set32(value vb, value vind, value newval)
+{
+ intnat idx = Long_val(vind);
+ struct caml_ba_array * b = Caml_ba_array_val(vb);
+ if (idx < 0 || idx >= b->dim[0] - 3) caml_array_bound_error();
+ unsigned char b1, b2, b3, b4;
+ intnat val = Int32_val(newval);
+#ifdef ARCH_BIG_ENDIAN
+ b1 = 0xFF & val >> 24;
+ b2 = 0xFF & val >> 16;
+ b3 = 0xFF & val >> 8;
+ b4 = 0xFF & val;
+#else
+ b4 = 0xFF & val >> 24;
+ b3 = 0xFF & val >> 16;
+ b2 = 0xFF & val >> 8;
+ b1 = 0xFF & val;
+#endif
+ ((unsigned char*) b->data)[idx] = b1;
+ ((unsigned char*) b->data)[idx+1] = b2;
+ ((unsigned char*) b->data)[idx+2] = b3;
+ ((unsigned char*) b->data)[idx+3] = b4;
+ return Val_unit;
+}
+
+CAMLprim value caml_ba_uint8_set64(value vb, value vind, value newval)
+{
+ intnat idx = Long_val(vind);
+ struct caml_ba_array * b = Caml_ba_array_val(vb);
+ if (idx < 0 || idx >= b->dim[0] - 7) caml_array_bound_error();
+ unsigned char b1, b2, b3, b4, b5, b6, b7, b8;
+ int64 val = Int64_val(newval);
+ uint32 lo,hi;
+ I64_split(val,hi,lo);
+#ifdef ARCH_BIG_ENDIAN
+ b1 = 0xFF & hi >> 24;
+ b2 = 0xFF & hi >> 16;
+ b3 = 0xFF & hi >> 8;
+ b4 = 0xFF & hi;
+ b5 = 0xFF & lo >> 24;
+ b6 = 0xFF & lo >> 16;
+ b7 = 0xFF & lo >> 8;
+ b8 = 0xFF & lo;
+#else
+ b8 = 0xFF & hi >> 24;
+ b7 = 0xFF & hi >> 16;
+ b6 = 0xFF & hi >> 8;
+ b5 = 0xFF & hi;
+ b4 = 0xFF & lo >> 24;
+ b3 = 0xFF & lo >> 16;
+ b2 = 0xFF & lo >> 8;
+ b1 = 0xFF & lo;
+#endif
+ ((unsigned char*) b->data)[idx] = b1;
+ ((unsigned char*) b->data)[idx+1] = b2;
+ ((unsigned char*) b->data)[idx+2] = b3;
+ ((unsigned char*) b->data)[idx+3] = b4;
+ ((unsigned char*) b->data)[idx+4] = b5;
+ ((unsigned char*) b->data)[idx+5] = b6;
+ ((unsigned char*) b->data)[idx+6] = b7;
+ ((unsigned char*) b->data)[idx+7] = b8;
+ return Val_unit;
+}
+
/* Return the number of dimensions of a big array */
CAMLprim value caml_ba_num_dims(value vb)
diff --git a/testsuite/tests/prim-bigstring/Makefile b/testsuite/tests/prim-bigstring/Makefile
new file mode 100644
index 0000000..5bfaa03
--- /dev/null
+++ b/testsuite/tests/prim-bigstring/Makefile
@@ -0,0 +1,5 @@
+BASEDIR=../..
+LIBRARIES=unix bigarray
+
+include $(BASEDIR)/makefiles/Makefile.several
+include $(BASEDIR)/makefiles/Makefile.common
diff --git a/testsuite/tests/prim-bigstring/bigstring_access.ml b/testsuite/tests/prim-bigstring/bigstring_access.ml
new file mode 100644
index 0000000..37b7285
--- /dev/null
+++ b/testsuite/tests/prim-bigstring/bigstring_access.ml
@@ -0,0 +1,86 @@
+
+open Bigarray
+type bigstring = (char, int8_unsigned_elt, c_layout) Array1.t
+
+external caml_bigstring_get_16 : bigstring -> int -> int = "%caml_bigstring_get16"
+external caml_bigstring_get_32 : bigstring -> int -> int32 = "%caml_bigstring_get32"
+external caml_bigstring_get_64 : bigstring -> int -> int64 = "%caml_bigstring_get64"
+
+external caml_bigstring_set_16 : bigstring -> int -> int -> unit = "%caml_bigstring_set16"
+external caml_bigstring_set_32 : bigstring -> int -> int32 -> unit = "%caml_bigstring_set32"
+external caml_bigstring_set_64 : bigstring -> int -> int64 -> unit = "%caml_bigstring_set64"
+
+let bigstring_of_string s =
+ let a = Array1.create char c_layout (String.length s) in
+ for i = 0 to String.length s - 1 do
+ a.{i} <- s.[i]
+ done;
+ a
+
+let s = bigstring_of_string (String.make 10 '\x00')
+
+let assert_bound_check2 f v1 v2 =
+ try
+ ignore(f v1 v2);
+ assert false
+ with
+ | Invalid_argument("index out of bounds") -> ()
+
+let assert_bound_check3 f v1 v2 v3 =
+ try
+ ignore(f v1 v2 v3);
+ assert false
+ with
+ | Invalid_argument("index out of bounds") -> ()
+
+let () =
+ assert_bound_check2 caml_bigstring_get_16 s (-1);
+ assert_bound_check2 caml_bigstring_get_16 s 9;
+ assert_bound_check2 caml_bigstring_get_32 s (-1);
+ assert_bound_check2 caml_bigstring_get_32 s 7;
+ assert_bound_check2 caml_bigstring_get_64 s (-1);
+ assert_bound_check2 caml_bigstring_get_64 s 3;
+
+ assert_bound_check3 caml_bigstring_set_16 s (-1) 0;
+ assert_bound_check3 caml_bigstring_set_16 s 9 0;
+ assert_bound_check3 caml_bigstring_set_32 s (-1) 0l;
+ assert_bound_check3 caml_bigstring_set_32 s 7 0l;
+ assert_bound_check3 caml_bigstring_set_64 s (-1) 0L;
+ assert_bound_check3 caml_bigstring_set_64 s 3 0L
+
+
+let () =
+ caml_bigstring_set_16 s 0 0x1234;
+ Printf.printf "%x %x %x\n%!"
+ (caml_bigstring_get_16 s 0)
+ (caml_bigstring_get_16 s 1)
+ (caml_bigstring_get_16 s 2);
+ caml_bigstring_set_16 s 0 0xFEDC;
+ Printf.printf "%x %x %x\n%!"
+ (caml_bigstring_get_16 s 0)
+ (caml_bigstring_get_16 s 1)
+ (caml_bigstring_get_16 s 2)
+
+let () =
+ caml_bigstring_set_32 s 0 0x12345678l;
+ Printf.printf "%lx %lx %lx\n%!"
+ (caml_bigstring_get_32 s 0)
+ (caml_bigstring_get_32 s 1)
+ (caml_bigstring_get_32 s 2);
+ caml_bigstring_set_32 s 0 0xFEDCBA09l;
+ Printf.printf "%lx %lx %lx\n%!"
+ (caml_bigstring_get_32 s 0)
+ (caml_bigstring_get_32 s 1)
+ (caml_bigstring_get_32 s 2)
+
+let () =
+ caml_bigstring_set_64 s 0 0x1234567890ABCDEFL;
+ Printf.printf "%Lx %Lx %Lx\n%!"
+ (caml_bigstring_get_64 s 0)
+ (caml_bigstring_get_64 s 1)
+ (caml_bigstring_get_64 s 2);
+ caml_bigstring_set_64 s 0 0xFEDCBA0987654321L;
+ Printf.printf "%Lx %Lx %Lx\n%!"
+ (caml_bigstring_get_64 s 0)
+ (caml_bigstring_get_64 s 1)
+ (caml_bigstring_get_64 s 2)
diff --git a/testsuite/tests/prim-bigstring/bigstring_access.reference b/testsuite/tests/prim-bigstring/bigstring_access.reference
new file mode 100644
index 0000000..22b25ad
--- /dev/null
+++ b/testsuite/tests/prim-bigstring/bigstring_access.reference
@@ -0,0 +1,6 @@
+1234 12 0
+fedc fe 0
+12345678 123456 1234
+fedcba09 fedcba fedc
+1234567890abcdef 1234567890abcd 1234567890ab
+fedcba0987654321 fedcba09876543 fedcba098765
diff --git a/testsuite/tests/prim-bigstring/string_access.ml b/testsuite/tests/prim-bigstring/string_access.ml
new file mode 100644
index 0000000..100c3b6
--- /dev/null
+++ b/testsuite/tests/prim-bigstring/string_access.ml
@@ -0,0 +1,79 @@
+
+external caml_string_get_16 : string -> int -> int = "%caml_string_get16"
+external caml_string_get_32 : string -> int -> int32 = "%caml_string_get32"
+external caml_string_get_64 : string -> int -> int64 = "%caml_string_get64"
+
+external caml_string_set_16 : string -> int -> int -> unit =
+ "%caml_string_set16"
+external caml_string_set_32 : string -> int -> int32 -> unit =
+ "%caml_string_set32"
+external caml_string_set_64 : string -> int -> int64 -> unit =
+ "%caml_string_set64"
+
+let s = String.make 10 '\x00'
+
+let assert_bound_check2 f v1 v2 =
+ try
+ ignore(f v1 v2);
+ assert false
+ with
+ | Invalid_argument("index out of bounds") -> ()
+
+let assert_bound_check3 f v1 v2 v3 =
+ try
+ ignore(f v1 v2 v3);
+ assert false
+ with
+ | Invalid_argument("index out of bounds") -> ()
+
+let () =
+ assert_bound_check2 caml_string_get_16 s (-1);
+ assert_bound_check2 caml_string_get_16 s 9;
+ assert_bound_check2 caml_string_get_32 s (-1);
+ assert_bound_check2 caml_string_get_32 s 7;
+ assert_bound_check2 caml_string_get_64 s (-1);
+ assert_bound_check2 caml_string_get_64 s 3;
+
+ assert_bound_check3 caml_string_set_16 s (-1) 0;
+ assert_bound_check3 caml_string_set_16 s 9 0;
+ assert_bound_check3 caml_string_set_32 s (-1) 0l;
+ assert_bound_check3 caml_string_set_32 s 7 0l;
+ assert_bound_check3 caml_string_set_64 s (-1) 0L;
+ assert_bound_check3 caml_string_set_64 s 3 0L
+
+
+let () =
+ caml_string_set_16 s 0 0x1234;
+ Printf.printf "%x %x %x\n%!"
+ (caml_string_get_16 s 0)
+ (caml_string_get_16 s 1)
+ (caml_string_get_16 s 2);
+ caml_string_set_16 s 0 0xFEDC;
+ Printf.printf "%x %x %x\n%!"
+ (caml_string_get_16 s 0)
+ (caml_string_get_16 s 1)
+ (caml_string_get_16 s 2)
+
+let () =
+ caml_string_set_32 s 0 0x12345678l;
+ Printf.printf "%lx %lx %lx\n%!"
+ (caml_string_get_32 s 0)
+ (caml_string_get_32 s 1)
+ (caml_string_get_32 s 2);
+ caml_string_set_32 s 0 0xFEDCBA09l;
+ Printf.printf "%lx %lx %lx\n%!"
+ (caml_string_get_32 s 0)
+ (caml_string_get_32 s 1)
+ (caml_string_get_32 s 2)
+
+let () =
+ caml_string_set_64 s 0 0x1234567890ABCDEFL;
+ Printf.printf "%Lx %Lx %Lx\n%!"
+ (caml_string_get_64 s 0)
+ (caml_string_get_64 s 1)
+ (caml_string_get_64 s 2);
+ caml_string_set_64 s 0 0xFEDCBA0987654321L;
+ Printf.printf "%Lx %Lx %Lx\n%!"
+ (caml_string_get_64 s 0)
+ (caml_string_get_64 s 1)
+ (caml_string_get_64 s 2)
diff --git a/testsuite/tests/prim-bigstring/string_access.reference b/testsuite/tests/prim-bigstring/string_access.reference
new file mode 100644
index 0000000..22b25ad
--- /dev/null
+++ b/testsuite/tests/prim-bigstring/string_access.reference
@@ -0,0 +1,6 @@
+1234 12 0
+fedc fe 0
+12345678 123456 1234
+fedcba09 fedcba fedc
+1234567890abcdef 1234567890abcd 1234567890ab
+fedcba0987654321 fedcba09876543 fedcba098765
--
1.7.10.4
| ||||||||||
Notes |
|
|
(0008211) gerd (reporter) 2012-10-06 21:24 |
Supporting this. I think we should also add primitives for nativeint, and for plain int (to avoid boxing when going through int32/int64). |
|
(0008212) chambart (reporter) 2012-10-07 00:26 |
It is not needed to add a special primitive for int, if you write a function like this: let f s i = Int32.to_int (caml_bigstring_get_32 s i) there will be no allocaion: the compiler avoid boxing the value |
|
(0008476) chambart (reporter) 2012-11-09 16:02 |
Add a version updated for current trunk. |
|
(0008478) lefessan (developer) 2012-11-09 17:15 |
Integrated in trunk at revision r13087. |
|
(0008616) frisch (developer) 2012-12-17 12:36 edited on: 2012-12-17 13:13 |
This commit breaks the MSVC port (in str.c and bigarray_stubs.c: it is not allowed to declare variables after the first statement in a function body). |
|
(0008632) frisch (developer) 2012-12-19 16:44 |
Same question as 0005774: what's the point of adding compiler support for those primitives if they are not exposed to user-land code? I understand this can be done in external libraries, but why not do it in stdlib? |
Issue History |
|||
| Date Modified | Username | Field | Change |
| 2012-10-02 16:02 | chambart | New Issue | |
| 2012-10-02 16:02 | chambart | File Added: 0001-Add-allow_unsigned_access-to-arch-description.patch | |
| 2012-10-02 16:02 | chambart | File Added: 0002-Add-primitives-to-load-and-write-directly-2-4-and-8-.patch | |
| 2012-10-06 21:24 | gerd | Note Added: 0008211 | |
| 2012-10-07 00:26 | chambart | Note Added: 0008212 | |
| 2012-11-09 16:02 | chambart | File Added: 0001-Add-primitives-to-load-and-write-2-4-and-8-bytes-to-.patch | |
| 2012-11-09 16:02 | chambart | Note Added: 0008476 | |
| 2012-11-09 16:54 | lefessan | File Deleted: 0001-Add-allow_unsigned_access-to-arch-description.patch | |
| 2012-11-09 16:54 | lefessan | File Deleted: 0002-Add-primitives-to-load-and-write-directly-2-4-and-8-.patch | |
| 2012-11-09 17:15 | lefessan | Note Added: 0008478 | |
| 2012-11-09 17:15 | lefessan | Status | new => resolved |
| 2012-11-09 17:15 | lefessan | Fixed in Version | => 4.01.0+dev |
| 2012-11-09 17:15 | lefessan | Resolution | open => fixed |
| 2012-11-09 17:15 | lefessan | Assigned To | => lefessan |
| 2012-12-17 12:36 | frisch | Note Added: 0008616 | |
| 2012-12-17 12:36 | frisch | Status | resolved => confirmed |
| 2012-12-17 13:13 | frisch | Note Edited: 0008616 | View Revisions |
| 2012-12-19 16:44 | frisch | Note Added: 0008632 | |
| Copyright © 2000 - 2011 MantisBT Group |



