Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(compiler): Allow exporting the function table #1870

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions cli/bin/grain.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ class GrainCommand extends commander.Command {
"--use-start-section",
"replaces the _start export with a start section during linking"
);
cmd.forwardOption(
"--export-function-table",
"causes the function table to be exported under the given name"
);
cmd.forwardOption(
"--no-pervasives",
"don't automatically import the Grain Pervasives module"
Expand Down
11 changes: 11 additions & 0 deletions compiler/src/linking/link.re
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,17 @@ let link_all = (linked_mod, dependencies, signature) => {
Type.funcref,
);

switch (Grain_utils.Config.export_function_table^) {
| Some(name) =>
ignore @@
Export.add_table_export(
linked_mod,
Comp_utils.grain_global_function_table,
name,
)
| None => ()
};

let (initial_memory, maximum_memory) =
switch (Config.initial_memory_pages^, Config.maximum_memory_pages^) {
| (initial_memory, Some(maximum_memory)) => (
Expand Down
8 changes: 8 additions & 0 deletions compiler/src/utils/config.re
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,14 @@ let use_start_section =
false,
);

let export_function_table =
opt(
~names=["export-function-table"],
~conv=option_conv(Cmdliner.Arg.string),
~doc="Causes the function table to be exported under the given name.",
None,
);

let elide_type_info =
toggle_flag(
~names=["elide-type-info"],
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/utils/config.rei
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ let wasi_polyfill: ref(option(string));

let use_start_section: ref(bool);

/** Weather to export the function table under a specifed name */
let export_function_table: ref(option(string));

/** Compilation profile, e.g. release for production builds */

let profile: ref(option(profile));
Expand Down
29 changes: 29 additions & 0 deletions compiler/test/suites/linking.re
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,35 @@ describe("linking", ({test, testSkip}) => {
);
});

test("export_function_table", ({expect}) => {
let name = "export_function_table";
let outfile = wasmfile(name);
ignore @@
compile(
~config_fn=
() => {Grain_utils.Config.export_function_table := Some("funcTable")},
name,
{|module Test; print("Hello, world!")|},
);
let ic = open_in_bin(outfile);
let sections = Grain_utils.Wasm_utils.get_wasm_sections(ic);
close_in(ic);
let export_sections =
List.find_map(
(sec: Grain_utils.Wasm_utils.wasm_bin_section) =>
switch (sec) {
| {sec_type: Export(exports)} => Some(exports)
| _ => None
},
sections,
);
expect.option(export_sections).toBeSome();
expect.list(Option.get(export_sections)).toContainEqual(
~equals=tuple_equal,
(WasmTable, "funcTable"),
);
});

test("import_memory", ({expect}) => {
let name = "import_memory";
let outfile = wasmfile(name);
Expand Down