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): Call known functions across module boundaries #1175

Merged
merged 5 commits into from
Apr 21, 2022
Merged
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
93 changes: 62 additions & 31 deletions compiler/src/codegen/comp_utils.re
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,26 @@ let grain_env_name = "_grainEnv";

let is_grain_env = str => grain_env_name == str;

let get_exported_names = (~local_names=?, wasm_mod) => {
let get_exported_names = (~function_names=?, ~global_names=?, wasm_mod) => {
let num_exports = Export.get_num_exports(wasm_mod);
let exported_names: Hashtbl.t(string, string) = Hashtbl.create(10);
for (i in 0 to num_exports - 1) {
let export = Export.get_export_by_index(wasm_mod, i);
let export_kind = Export.export_get_kind(export);
if (export_kind == Export.external_function
|| export_kind == Export.external_global) {
let exported_name = Export.get_name(export);
let internal_name = Export.get_value(export);
let exported_name = Export.get_name(export);
let internal_name = Export.get_value(export);
phated marked this conversation as resolved.
Show resolved Hide resolved

if (export_kind == Export.external_function) {
let new_internal_name =
switch (function_names) {
| Some(function_names) => Hashtbl.find(function_names, internal_name)
phated marked this conversation as resolved.
Show resolved Hide resolved
| None => internal_name
};
Hashtbl.add(exported_names, exported_name, new_internal_name);
} else if (export_kind == Export.external_global) {
let new_internal_name =
switch (local_names) {
| Some(local_names) => Hashtbl.find(local_names, internal_name)
switch (global_names) {
| Some(global_names) => Hashtbl.find(global_names, internal_name)
phated marked this conversation as resolved.
Show resolved Hide resolved
| None => internal_name
};
Hashtbl.add(exported_names, exported_name, new_internal_name);
Expand Down Expand Up @@ -133,47 +140,71 @@ let write_universal_exports =
List.iter(
item => {
switch (item) {
| TSigValue(id, {val_repr: ReprFunction(args, rets)}) =>
| TSigValue(
id,
{
val_repr: ReprFunction(args, rets, direct),
val_fullpath: path,
},
) =>
let name = Ident.name(id);
let exported_name = "GRAIN$EXPORT$" ++ name;
let internal_name = Hashtbl.find(exported_names, exported_name);
let internal_global_name =
Hashtbl.find(exported_names, exported_name);
let get_closure = () =>
Expression.Global_get.make(wasm_mod, internal_name, Type.int32);
Expression.Global_get.make(
wasm_mod,
internal_global_name,
Type.int32,
);
let arguments =
List.mapi(
(i, arg) =>
Expression.Local_get.make(wasm_mod, i, type_of_repr(arg)),
args,
);
let arguments = [get_closure(), ...arguments];
let call_arg_types =
Type.create(
Array.of_list(List.map(type_of_repr, [WasmI32, ...args])),
);
let call_result_types =
Type.create(
Array.of_list(
List.map(type_of_repr, rets == [] ? [WasmI32] : rets),
),
);
let func_ptr =
Expression.Load.make(
wasm_mod,
4,
8,
2,
Type.int32,
get_closure(),
);
let function_call =
Expression.Call_indirect.make(
wasm_mod,
global_function_table,
func_ptr,
arguments,
call_arg_types,
call_result_types,
);
switch (direct) {
| Direct(name) =>
Expression.Call.make(
wasm_mod,
Hashtbl.find(exported_names, name),
phated marked this conversation as resolved.
Show resolved Hide resolved
arguments,
call_result_types,
)
| Indirect =>
let call_arg_types =
Type.create(
Array.of_list(
List.map(type_of_repr, [WasmI32, ...args]),
),
);
let func_ptr =
Expression.Load.make(
wasm_mod,
4,
8,
2,
Type.int32,
get_closure(),
);
Expression.Call_indirect.make(
wasm_mod,
global_function_table,
func_ptr,
arguments,
call_arg_types,
call_result_types,
);
| Unknown => failwith("Impossible: Unknown function call type")
};
let function_body =
switch (rets) {
| [] => Expression.Drop.make(wasm_mod, function_call)
Expand Down
14 changes: 7 additions & 7 deletions compiler/src/codegen/compcore.re
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,8 @@ let get_wasm_imported_name = (~runtime_import=true, mod_, name) => {
Printf.sprintf("wimport_%s_%s", Ident.name(mod_), Ident.name(name));
};

let get_grain_imported_name = (mod_, name) => {
let get_grain_imported_name = (mod_, name) =>
Printf.sprintf("gimport_%s_%s", Ident.name(mod_), Ident.name(name));
};

let call_exception_printer = (wasm_mod, env, args) => {
let args = [
Expand Down Expand Up @@ -3323,14 +3322,15 @@ let compile_imports = (wasm_mod, env, {imports}) => {
| MImportWasm => Ident.name(name)
| MImportGrain => "GRAIN$MODULE$" ++ Ident.name(name);

let compile_import_name = name =>
fun
phated marked this conversation as resolved.
Show resolved Hide resolved
| MImportWasm => Ident.name(name)
| MImportGrain => "GRAIN$EXPORT$" ++ Ident.name(name);
let compile_import_name = (name, kind, ty) =>
switch (kind, ty) {
| (MImportGrain, MGlobalImport(_)) => "GRAIN$EXPORT$" ++ Ident.name(name)
| _ => Ident.name(name)
};

let compile_import = ({mimp_mod, mimp_name, mimp_type, mimp_kind}) => {
let module_name = compile_module_name(mimp_mod, mimp_kind);
let item_name = compile_import_name(mimp_name, mimp_kind);
let item_name = compile_import_name(mimp_name, mimp_kind, mimp_type);
let internal_name =
switch (mimp_kind) {
| MImportGrain => get_grain_imported_name(mimp_mod, mimp_name)
Expand Down
Loading