Skip to content

Commit 1c5478e

Browse files
authored
feat(compiler): Use Binaryen's bulk memory polyfill (#2334)
1 parent fafad72 commit 1c5478e

File tree

11 files changed

+77
-343
lines changed

11 files changed

+77
-343
lines changed

compiler/src/codegen/compcore.re

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ let gensym_label = s => {
3737
};
3838
let reset_labels = () => gensym_counter := 0;
3939

40+
/* Binaryen Features */
41+
let features = [
42+
Module.Feature.mvp,
43+
Module.Feature.multivalue,
44+
Module.Feature.tail_call,
45+
Module.Feature.sign_ext,
46+
Module.Feature.mutable_globals,
47+
Module.Feature.bulk_memory,
48+
Module.Feature.bulk_memory_opt,
49+
];
50+
4051
/* Number of swap variables to allocate */
4152
let swap_slots_i32 = [|Type.int32, Type.int32, Type.int32|];
4253
let swap_slots_i64 = [|Type.int64|];
@@ -3456,23 +3467,6 @@ let compile_wasm_module =
34563467
);
34573468
let wasm_mod = Module.create();
34583469

3459-
let default_features = [
3460-
Module.Feature.mvp,
3461-
Module.Feature.multivalue,
3462-
Module.Feature.tail_call,
3463-
Module.Feature.sign_ext,
3464-
Module.Feature.mutable_globals,
3465-
];
3466-
let features =
3467-
if (Config.bulk_memory^) {
3468-
[
3469-
Module.Feature.bulk_memory,
3470-
Module.Feature.bulk_memory_opt,
3471-
...default_features,
3472-
];
3473-
} else {
3474-
default_features;
3475-
};
34763470
let _ = Module.set_features(wasm_mod, features);
34773471
// we set low_memory_unused := true if and only if the user has not specified a memory base.
34783472
// This is because in many use cases in which this is specified (e.g. wasm4), users
@@ -3538,6 +3532,11 @@ let compile_wasm_module =
35383532

35393533
validate_module(~name?, wasm_mod);
35403534

3535+
// Binaryen pass for polyfilling for memory.copy/fill if bulk memory is not enabled
3536+
if (! Config.bulk_memory^) {
3537+
Module.run_passes(wasm_mod, [Passes.llvm_memory_copy_fill_lowering]);
3538+
};
3539+
35413540
switch (Config.profile^) {
35423541
| Some(Release) => Optimize_mod.optimize(wasm_mod)
35433542
| None => ()

compiler/src/codegen/compcore.rei

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ open Grain_middle_end;
33
open Mashtree;
44
open Binaryen;
55

6+
let features: list(Module.Feature.t);
7+
68
exception WasmRunnerError(Module.t, option(string), string);
79

810
let validate_module: (~name: string=?, Module.t) => unit;

compiler/src/middle_end/analyze_inline_wasm.re

Lines changed: 0 additions & 75 deletions
This file was deleted.

compiler/src/middle_end/analyze_inline_wasm.rei

Lines changed: 0 additions & 12 deletions
This file was deleted.

compiler/src/middle_end/optimize.re

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ let analysis_passes = [
66
Analyze_manual_memory_management.analyze,
77
Analyze_purity.analyze,
88
Analyze_tail_calls.analyze,
9-
Analyze_inline_wasm.analyze,
109
Analyze_free_vars.analyze,
1110
Analyze_closure_scoped_vars.analyze,
1211
Analyze_mutable_vars.analyze,
@@ -20,7 +19,6 @@ let optimization_passes = [
2019
Optimize_dead_assignments.optimize,
2120
Optimize_dead_branches.optimize,
2221
Optimize_dead_statements.optimize,
23-
Optimize_inline_wasm.optimize,
2422
Optimize_local_mutations.optimize,
2523
];
2624

compiler/src/middle_end/optimize_inline_wasm.re

Lines changed: 0 additions & 34 deletions
This file was deleted.

compiler/src/middle_end/optimize_inline_wasm.rei

Lines changed: 0 additions & 3 deletions
This file was deleted.

compiler/src/typed/typecore.re

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,16 +368,16 @@ let primn_type =
368368
| WasmMemoryCopy =>
369369
prim_type(
370370
[
371-
("source", Builtin_types.type_wasmi32),
372-
("destination", Builtin_types.type_wasmi32),
371+
("dest", Builtin_types.type_wasmi32),
372+
("src", Builtin_types.type_wasmi32),
373373
("length", Builtin_types.type_wasmi32),
374374
],
375375
Builtin_types.type_void,
376376
)
377377
| WasmMemoryFill =>
378378
prim_type(
379379
[
380-
("ptr", Builtin_types.type_wasmi32),
380+
("dest", Builtin_types.type_wasmi32),
381381
("value", Builtin_types.type_wasmi32),
382382
("length", Builtin_types.type_wasmi32),
383383
],

compiler/test/suites/flags.re

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
open Grain_tests.TestFramework;
2+
open Grain_tests.Runner;
3+
open Grain_codegen;
4+
open Binaryen;
5+
6+
let load_module = fullpath => {
7+
let ic = open_in_bin(fullpath);
8+
let length = in_channel_length(ic);
9+
let module_bytes = Bytes.create(length);
10+
really_input(ic, module_bytes, 0, length);
11+
close_in(ic);
12+
Module.read(module_bytes);
13+
};
14+
15+
describe("flags", ({test, testSkip}) => {
16+
// Test --no-bulk-memory polyfill
17+
test("no_bulk_memory_calls", ({expect}) => {
18+
let name = "no_bulk_memory_calls";
19+
let outfile = wasmfile(name);
20+
ignore @@
21+
compile(
22+
~link=true,
23+
~config_fn=() => {Grain_utils.Config.bulk_memory := false},
24+
name,
25+
{|
26+
module NoBulkMemoryCalls
27+
28+
from "runtime/unsafe/memory" include Memory
29+
@unsafe
30+
provide let foo = Memory.fill
31+
@unsafe
32+
provide let bar = Memory.copy
33+
|},
34+
);
35+
let wasm_mod = load_module(outfile);
36+
Module.set_features(
37+
wasm_mod,
38+
List.filter(
39+
f =>
40+
f != Module.Feature.bulk_memory
41+
&& f != Module.Feature.bulk_memory_opt,
42+
Compcore.features,
43+
),
44+
);
45+
expect.bool(
46+
List.mem(Module.Feature.bulk_memory, Module.get_features(wasm_mod)),
47+
).
48+
toBe(
49+
false,
50+
);
51+
// The module will fail validation if bulk memory opcodes are still present
52+
expect.int(Module.validate(wasm_mod)).toBe(1);
53+
})
54+
});

0 commit comments

Comments
 (0)