Skip to content

Commit 2dba010

Browse files
authored
fix(compiler): Write universal exports on linked module (#2234)
1 parent e3a4eac commit 2dba010

File tree

8 files changed

+210
-402
lines changed

8 files changed

+210
-402
lines changed

compiler/src/codegen/comp_utils.re

Lines changed: 124 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -153,36 +153,6 @@ let load =
153153
);
154154
};
155155

156-
let is_grain_env = str => grain_env_name == str;
157-
158-
let get_exported_names = (~function_names=?, ~global_names=?, wasm_mod) => {
159-
let num_exports = Export.get_num_exports(wasm_mod);
160-
let exported_names: Hashtbl.t(string, string) = Hashtbl.create(10);
161-
for (i in 0 to num_exports - 1) {
162-
let export = Export.get_export_by_index(wasm_mod, i);
163-
let export_kind = Export.export_get_kind(export);
164-
let exported_name = Export.get_name(export);
165-
let internal_name = Export.get_value(export);
166-
167-
if (export_kind == Export.external_function) {
168-
let new_internal_name =
169-
switch (function_names) {
170-
| Some(function_names) => Hashtbl.find(function_names, internal_name)
171-
| None => internal_name
172-
};
173-
Hashtbl.add(exported_names, exported_name, new_internal_name);
174-
} else if (export_kind == Export.external_global) {
175-
let new_internal_name =
176-
switch (global_names) {
177-
| Some(global_names) => Hashtbl.find(global_names, internal_name)
178-
| None => internal_name
179-
};
180-
Hashtbl.add(exported_names, exported_name, new_internal_name);
181-
};
182-
};
183-
exported_names;
184-
};
185-
186156
let type_of_repr = repr => {
187157
Types.(
188158
switch (repr) {
@@ -195,152 +165,147 @@ let type_of_repr = repr => {
195165
};
196166

197167
let write_universal_exports =
198-
(wasm_mod, {Cmi_format.cmi_sign}, exported_names) => {
199-
Types.(
200-
Type_utils.(
201-
List.iter(
202-
item => {
203-
switch (item) {
204-
| TSigValue(
205-
id,
206-
{
207-
val_repr: ReprFunction(args, rets, direct),
208-
val_fullpath: path,
209-
},
210-
) =>
211-
let name = Ident.name(id);
212-
let exported_name = "GRAIN$EXPORT$" ++ name;
213-
let internal_global_name =
214-
Hashtbl.find(exported_names, exported_name);
215-
let get_closure = () =>
216-
Expression.Global_get.make(
168+
(wasm_mod, {Cmi_format.cmi_sign}, exports, resolve) => {
169+
open Types;
170+
open Type_utils;
171+
let export_map = Hashtbl.create(128);
172+
List.iter(
173+
e => {
174+
switch (e) {
175+
| WasmGlobalExport({ex_global_name, ex_global_internal_name}) =>
176+
Hashtbl.add(
177+
export_map,
178+
ex_global_name,
179+
resolve(ex_global_internal_name),
180+
)
181+
// All functions have an associated global
182+
| WasmFunctionExport(_) => ()
183+
}
184+
},
185+
exports,
186+
);
187+
List.iter(
188+
item => {
189+
switch (item) {
190+
| TSigValue(id, {val_repr: ReprFunction(args, rets, direct)}) =>
191+
let name = Ident.name(id);
192+
let internal_name = Hashtbl.find(export_map, name);
193+
let get_closure = () =>
194+
Expression.Global_get.make(wasm_mod, internal_name, Type.int32);
195+
let arguments =
196+
List.mapi(
197+
(i, arg) =>
198+
Expression.Local_get.make(wasm_mod, i, type_of_repr(arg)),
199+
args,
200+
);
201+
let arguments = [get_closure(), ...arguments];
202+
let call_result_types =
203+
Type.create(
204+
Array.of_list(
205+
List.map(type_of_repr, rets == [] ? [WasmI32] : rets),
206+
),
207+
);
208+
let function_call =
209+
switch (direct) {
210+
| Direct({name}) =>
211+
Expression.Call.make(
212+
wasm_mod,
213+
internal_name,
214+
arguments,
215+
call_result_types,
216+
)
217+
| Indirect =>
218+
let call_arg_types =
219+
Type.create(
220+
Array.of_list(List.map(type_of_repr, [WasmI32, ...args])),
221+
);
222+
let func_ptr =
223+
Expression.Load.make(
217224
wasm_mod,
218-
internal_global_name,
225+
4,
226+
8,
227+
2,
219228
Type.int32,
229+
get_closure(),
230+
grain_memory,
220231
);
221-
let arguments =
222-
List.mapi(
223-
(i, arg) =>
224-
Expression.Local_get.make(wasm_mod, i, type_of_repr(arg)),
225-
args,
226-
);
227-
let arguments = [get_closure(), ...arguments];
228-
let call_result_types =
229-
Type.create(
230-
Array.of_list(
231-
List.map(type_of_repr, rets == [] ? [WasmI32] : rets),
232+
Expression.Call_indirect.make(
233+
wasm_mod,
234+
grain_global_function_table,
235+
func_ptr,
236+
arguments,
237+
call_arg_types,
238+
call_result_types,
239+
);
240+
| Unknown => failwith("Impossible: Unknown function call type")
241+
};
242+
let function_body =
243+
switch (rets) {
244+
| [] => Expression.Drop.make(wasm_mod, function_call)
245+
| _ => function_call
246+
};
247+
let function_body =
248+
Expression.Block.make(
249+
wasm_mod,
250+
"closure_incref",
251+
[
252+
Expression.If.make(
253+
wasm_mod,
254+
Expression.Binary.make(
255+
wasm_mod,
256+
Op.ne_int32,
257+
get_closure(),
258+
Expression.Const.make(wasm_mod, Literal.int32(0l)),
232259
),
233-
);
234-
let function_call =
235-
switch (direct) {
236-
| Direct({name}) =>
237-
Expression.Call.make(
260+
store(
238261
wasm_mod,
239-
Hashtbl.find(exported_names, name),
240-
arguments,
241-
call_result_types,
242-
)
243-
| Indirect =>
244-
let call_arg_types =
245-
Type.create(
246-
Array.of_list(
247-
List.map(type_of_repr, [WasmI32, ...args]),
248-
),
249-
);
250-
let func_ptr =
251-
Expression.Load.make(
262+
Expression.Binary.make(
252263
wasm_mod,
253-
4,
254-
8,
255-
2,
256-
Type.int32,
264+
Op.sub_int32,
257265
get_closure(),
258-
grain_memory,
259-
);
260-
Expression.Call_indirect.make(
261-
wasm_mod,
262-
grain_global_function_table,
263-
func_ptr,
264-
arguments,
265-
call_arg_types,
266-
call_result_types,
267-
);
268-
| Unknown => failwith("Impossible: Unknown function call type")
269-
};
270-
let function_body =
271-
switch (rets) {
272-
| [] => Expression.Drop.make(wasm_mod, function_call)
273-
| _ => function_call
274-
};
275-
let function_body =
276-
Expression.Block.make(
277-
wasm_mod,
278-
"closure_incref",
279-
[
280-
Expression.If.make(
266+
Expression.Const.make(wasm_mod, Literal.int32(8l)),
267+
),
268+
Expression.Binary.make(
281269
wasm_mod,
282-
Expression.Binary.make(
283-
wasm_mod,
284-
Op.ne_int32,
285-
get_closure(),
286-
Expression.Const.make(wasm_mod, Literal.int32(0l)),
287-
),
288-
store(
270+
Op.add_int32,
271+
load(
289272
wasm_mod,
290273
Expression.Binary.make(
291274
wasm_mod,
292275
Op.sub_int32,
293276
get_closure(),
294277
Expression.Const.make(wasm_mod, Literal.int32(8l)),
295278
),
296-
Expression.Binary.make(
297-
wasm_mod,
298-
Op.add_int32,
299-
load(
300-
wasm_mod,
301-
Expression.Binary.make(
302-
wasm_mod,
303-
Op.sub_int32,
304-
get_closure(),
305-
Expression.Const.make(
306-
wasm_mod,
307-
Literal.int32(8l),
308-
),
309-
),
310-
),
311-
Expression.Const.make(wasm_mod, Literal.int32(1l)),
312-
),
313279
),
314-
Expression.Null.make(),
280+
Expression.Const.make(wasm_mod, Literal.int32(1l)),
315281
),
316-
function_body,
317-
],
318-
);
319-
let arg_types =
320-
Type.create(Array.of_list(List.map(type_of_repr, args)));
321-
let result_types =
322-
Type.create(Array.of_list(List.map(type_of_repr, rets)));
323-
ignore @@
324-
Function.add_function(
325-
wasm_mod,
326-
name,
327-
arg_types,
328-
result_types,
329-
[||],
282+
),
283+
Expression.Null.make(),
284+
),
330285
function_body,
331-
);
332-
// Remove existing Grain export (if any)
333-
Export.remove_export(wasm_mod, name);
334-
ignore @@ Export.add_function_export(wasm_mod, name, name);
335-
| TSigValue(_)
336-
| TSigType(_)
337-
| TSigTypeExt(_)
338-
| TSigModule(_)
339-
| TSigModType(_) => ()
340-
}
341-
},
342-
cmi_sign,
343-
)
344-
)
286+
],
287+
);
288+
let arg_types =
289+
Type.create(Array.of_list(List.map(type_of_repr, args)));
290+
let result_types =
291+
Type.create(Array.of_list(List.map(type_of_repr, rets)));
292+
ignore @@
293+
Function.add_function(
294+
wasm_mod,
295+
name,
296+
arg_types,
297+
result_types,
298+
[||],
299+
function_body,
300+
);
301+
ignore @@ Export.add_function_export(wasm_mod, name, name);
302+
| TSigValue(_)
303+
| TSigType(_)
304+
| TSigTypeExt(_)
305+
| TSigModule(_)
306+
| TSigModType(_) => ()
307+
}
308+
},
309+
cmi_sign,
345310
);
346311
};

compiler/src/codegen/comp_utils.rei

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,5 @@ let load:
5353
) =>
5454
Expression.t;
5555

56-
let is_grain_env: string => bool;
57-
58-
let get_exported_names:
59-
(
60-
~function_names: Hashtbl.t(string, string)=?,
61-
~global_names: Hashtbl.t(string, string)=?,
62-
Module.t
63-
) =>
64-
Hashtbl.t(string, string);
65-
6656
let write_universal_exports:
67-
(Module.t, Cmi_format.cmi_infos, Hashtbl.t(string, string)) => unit;
57+
(Module.t, Cmi_format.cmi_infos, list(export), string => string) => unit;

0 commit comments

Comments
 (0)