Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 0 additions & 96 deletions compiler/src/codegen/compcore.re
Original file line number Diff line number Diff line change
Expand Up @@ -2066,102 +2066,6 @@ let compile_primn = (wasm_mod, env: codegen_env, p, args): Expression.t => {
const_void(wasm_mod),
],
)
| WasmMemoryCompare =>
let lbl = gensym_label("memory_compare");
let loop_lbl = gensym_label("memory_compare_loop");
let set_ptr1 = set_swap(~ty=WasmValue(WasmI32), wasm_mod, env, 0);
let set_ptr2 = set_swap(~ty=WasmValue(WasmI32), wasm_mod, env, 1);
let set_count = set_swap(~ty=WasmValue(WasmI32), wasm_mod, env, 2);
let get_ptr1 = () => get_swap(~ty=WasmValue(WasmI32), wasm_mod, env, 0);
let get_ptr2 = () => get_swap(~ty=WasmValue(WasmI32), wasm_mod, env, 1);
let get_count = () => get_swap(~ty=WasmValue(WasmI32), wasm_mod, env, 2);
Expression.Block.make(
wasm_mod,
lbl,
[
set_ptr1(compile_imm(wasm_mod, env, List.nth(args, 0))),
set_ptr2(compile_imm(wasm_mod, env, List.nth(args, 1))),
set_count(compile_imm(wasm_mod, env, List.nth(args, 2))),
Expression.Loop.make(
wasm_mod,
loop_lbl,
Expression.Block.make(
wasm_mod,
gensym_label("memory_compare_loop_inner"),
[
Expression.Drop.make(wasm_mod) @@
Expression.Break.make(
wasm_mod,
lbl,
Expression.Unary.make(wasm_mod, Op.eq_z_int32, get_count()),
Expression.Const.make(wasm_mod, const_int32(0)),
),
Expression.If.make(
wasm_mod,
Expression.Binary.make(
wasm_mod,
Op.ne_int32,
load(~sz=1, ~signed=false, wasm_mod, get_ptr1()),
load(~sz=1, ~signed=false, wasm_mod, get_ptr2()),
),
Expression.Break.make(
wasm_mod,
lbl,
Expression.Null.make(),
Expression.Select.make(
wasm_mod,
Expression.Binary.make(
wasm_mod,
Op.lt_u_int32,
load(~sz=1, ~signed=false, wasm_mod, get_ptr1()),
load(~sz=1, ~signed=false, wasm_mod, get_ptr2()),
),
Expression.Const.make(wasm_mod, const_int32(-1)),
Expression.Const.make(wasm_mod, const_int32(1)),
),
),
Expression.Block.make(
wasm_mod,
gensym_label("memory_compare_loop_incr"),
[
set_ptr1(
Expression.Binary.make(
wasm_mod,
Op.add_int32,
get_ptr1(),
Expression.Const.make(wasm_mod, const_int32(1)),
),
),
set_ptr2(
Expression.Binary.make(
wasm_mod,
Op.add_int32,
get_ptr2(),
Expression.Const.make(wasm_mod, const_int32(1)),
),
),
set_count(
Expression.Binary.make(
wasm_mod,
Op.sub_int32,
get_count(),
Expression.Const.make(wasm_mod, const_int32(1)),
),
),
Expression.Break.make(
wasm_mod,
loop_lbl,
Expression.Null.make(),
Expression.Null.make(),
),
],
),
),
],
),
),
],
);
| WasmRefArraySet({array_type}) =>
let array_type = get_array_type(~env, array_type);
Expression.Block.make(
Expand Down
1 change: 0 additions & 1 deletion compiler/src/codegen/mashtree.re
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,6 @@ type primn =
| WasmStoreF64
| WasmMemoryCopy
| WasmMemoryFill
| WasmMemoryCompare
| WasmRefArraySet({array_type: wasm_array_type})
| WasmRefArrayCopy({array_type: wasm_array_type})
| WasmRefArrayFill({array_type: wasm_array_type})
Expand Down
1 change: 0 additions & 1 deletion compiler/src/middle_end/analyze_purity.re
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ module PurityArg: Anf_iterator.IterArgument = {
WasmStoreI32(_) | WasmStoreI64(_) | WasmStoreF32 | WasmStoreF64 |
WasmMemoryCopy |
WasmMemoryFill |
WasmMemoryCompare |
WasmRefArraySet(_) |
WasmRefArrayCopy(_) |
WasmRefArrayFill(_),
Expand Down
1 change: 0 additions & 1 deletion compiler/src/middle_end/anftree.re
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ type primn =
| WasmStoreF64
| WasmMemoryCopy
| WasmMemoryFill
| WasmMemoryCompare
| WasmRefArraySet({array_type: wasm_array_type})
| WasmRefArrayCopy({array_type: wasm_array_type})
| WasmRefArrayFill({array_type: wasm_array_type})
Expand Down
1 change: 0 additions & 1 deletion compiler/src/middle_end/anftree.rei
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,6 @@ type primn =
| WasmStoreF64
| WasmMemoryCopy
| WasmMemoryFill
| WasmMemoryCompare
| WasmRefArraySet({array_type: wasm_array_type})
| WasmRefArrayCopy({array_type: wasm_array_type})
| WasmRefArrayFill({array_type: wasm_array_type})
Expand Down
1 change: 0 additions & 1 deletion compiler/src/parsing/parsetree.re
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,6 @@ type primn =
| WasmStoreF64
| WasmMemoryCopy
| WasmMemoryFill
| WasmMemoryCompare
| WasmRefArraySet({array_type: wasm_array_type})
| WasmRefArrayCopy({array_type: wasm_array_type})
| WasmRefArrayFill({array_type: wasm_array_type})
Expand Down
2 changes: 0 additions & 2 deletions compiler/src/typed/translprim.re
Original file line number Diff line number Diff line change
Expand Up @@ -1546,7 +1546,6 @@ let prim_map =
("@wasm.memory_size", Primitive0(WasmMemorySize)),
("@wasm.memory_copy", PrimitiveN(WasmMemoryCopy)),
("@wasm.memory_fill", PrimitiveN(WasmMemoryFill)),
("@wasm.memory_compare", PrimitiveN(WasmMemoryCompare)),
("@wasm.ref_array_len", Primitive1(WasmRefArrayLen)),
(
"@wasm.ref_array_i8_get_s",
Expand Down Expand Up @@ -1699,7 +1698,6 @@ let transl_prim = (env, desc) => {
| WasmStoreF64
| WasmMemoryCopy
| WasmMemoryFill
| WasmMemoryCompare
| WasmRefArraySet(_) => (
[lambda_arg(pat_a), lambda_arg(pat_b), lambda_arg(pat_c)],
[id_a, id_b, id_c],
Expand Down
9 changes: 0 additions & 9 deletions compiler/src/typed/typecore.re
Original file line number Diff line number Diff line change
Expand Up @@ -504,15 +504,6 @@ let primn_type =
],
Builtin_types.type_void,
)
| WasmMemoryCompare =>
prim_type(
[
("ptr1", Builtin_types.type_wasmi32),
("ptr2", Builtin_types.type_wasmi32),
("length", Builtin_types.type_wasmi32),
],
Builtin_types.type_wasmi32,
)
| WasmRefArraySet({array_type: Wasm_packed_i8}) =>
prim_type(
[
Expand Down
1 change: 0 additions & 1 deletion compiler/src/typed/typedtree.re
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ type primn =
| WasmStoreF64
| WasmMemoryCopy
| WasmMemoryFill
| WasmMemoryCompare
| WasmRefArraySet({array_type: wasm_array_type})
| WasmRefArrayCopy({array_type: wasm_array_type})
| WasmRefArrayFill({array_type: wasm_array_type})
Expand Down
1 change: 0 additions & 1 deletion compiler/src/typed/typedtree.rei
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,6 @@ type primn =
| WasmStoreF64
| WasmMemoryCopy
| WasmMemoryFill
| WasmMemoryCompare
| WasmRefArraySet({array_type: wasm_array_type})
| WasmRefArrayCopy({array_type: wasm_array_type})
| WasmRefArrayFill({array_type: wasm_array_type})
Expand Down
84 changes: 84 additions & 0 deletions compiler/test/runtime/unsafe/memory.test.gr
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
module MemoryTest

from "runtime/unsafe/wasmi32" include WasmI32
from "runtime/unsafe/memory" include Memory
from "runtime/malloc" include Malloc

from "runtime/debugPrint" include DebugPrint

// Memory.copy
@unsafe
let test = () => {
use WasmI32.{ (+), (-), (==), ltU as (<), gtU as (>) }
let length = 10n
let section1 = Malloc.malloc(length)
let section2 = Malloc.malloc(length)
// Clear both sections byte by byte
for (let mut i = 0n; i < length; i += 1n) {
WasmI32.store8(section1, 0n, i)
WasmI32.store8(section2, 0n, i)
}
// Set section1 to 1,2,...length
for (let mut i = 0n; i < length; i += 1n) {
WasmI32.store8(section1, i, i)
}
// Copy section1 to section2
Memory.copy(section2, section1, length)
// Verify the copy was successful
for (let mut i = 0n; i < length; i += 1n) {
assert WasmI32.load8U(section1, i) == WasmI32.load8U(section2, i)
}
// Verify that overlapping regions are handled correctly by copying section1 to itself with an offset
let shift = 2n
Memory.copy(section1, section1 + shift, length - shift)
for (let mut i = 0n; i < length - shift; i += 1n) {
assert WasmI32.load8U(section1, i) == i + shift
}
}
test()

// Memory.fill
@unsafe
let test = () => {
use WasmI32.{ (+), (==), ltU as (<) }
let length = 10n
let section = Malloc.malloc(10n)
// Clear the section byte by byte
for (let mut i = 0n; i < length; i += 1n) {
WasmI32.store8(section, 0n, i)
}
// Fill the section with `255`
Memory.fill(section, 255n, length)
// Verify the fill was successful
for (let mut i = 0n; i < length; i += 1n) {
assert WasmI32.load8U(section, i) == 255n
}
}
test()

// Memory.compare
@unsafe
let test = () => {
use WasmI32.{ (-), (==), (<), (>) }
let length = 10n
let section1 = Malloc.malloc(length)
let section2 = Malloc.malloc(length)
// Equal regions
Memory.fill(section1, 0n, length)
Memory.fill(section2, 0n, length)
assert Memory.compare(section1, section2, 0n) == 0n
// First region less than second
Memory.fill(section1, 0n, length)
Memory.fill(section2, 1n, length)
assert Memory.compare(section1, section2, length) < 0n
// First region greater than second
Memory.fill(section1, 1n, length)
Memory.fill(section2, 0n, length)
assert Memory.compare(section1, section2, length) > 0n
// Regions differ at the last byte
Memory.fill(section1, 0n, length)
WasmI32.store8(section1, 255n, length - 1n)
Memory.fill(section2, 0n, length)
assert Memory.compare(section1, section2, length) > 0n
}
test()
1 change: 1 addition & 0 deletions compiler/test/suites/runtime.re
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ describe("runtime", ({test, testSkip}) => {
assertRuntime("unsafe/wasmi32.test");
assertRuntime("unsafe/wasmi64.test");
assertRuntime("unsafe/wasmref.test");
assertRuntime("unsafe/memory.test");
});
10 changes: 9 additions & 1 deletion stdlib/runtime/unsafe/memory.gr
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@ provide primitive fill = "@wasm.memory_fill"
*
* @returns `0` if the memory regions are equal, a negative value if the first region is less than the second, and a positive value if the first region is greater than the second.
*/
provide primitive compare = "@wasm.memory_compare"
provide let compare = (ptr1: WasmI32, ptr2: WasmI32, length: WasmI32) => {
use WasmI32.{ (!=), (-) }
for (let mut i = 0n; i < length; i += 1n) {
let byte1 = WasmI32.load8U(ptr1, i)
let byte2 = WasmI32.load8U(ptr2, i)
if (byte1 != byte2) return byte1 - byte2
}
return 0n
}

/**
* Copies data from a (array i8) to linear memory.
Expand Down
Loading