Skip to content

Commit de9d250

Browse files
committed
Add test for EM_JS and i64 arguments
Ideally we should error out if WASM_BIGINT is not passed by I have yet to find a good place to do that. See #15871
1 parent a6721f6 commit de9d250

File tree

5 files changed

+68
-6
lines changed

5 files changed

+68
-6
lines changed

emscripten.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,24 @@ def emscript(in_wasm, out_wasm, outfile_js, memfile):
299299

300300
update_settings_glue(metadata)
301301

302+
if not settings.WASM_BIGINT and metadata['emJsFuncs']:
303+
module = webassembly.Module(in_wasm)
304+
types = module.get_types()
305+
import_map = {}
306+
for imp in module.get_imports():
307+
import_map[imp.field] = imp
308+
for em_js_func, raw in metadata.get('emJsFuncs', {}).items():
309+
c_sig = raw.split('<::>')[0].strip('()')
310+
if c_sig:
311+
c_sig = c_sig.split(',')
312+
else:
313+
c_sig = []
314+
imp = import_map[em_js_func]
315+
assert(imp.kind == webassembly.ExternType.FUNC)
316+
signature = types[imp.type]
317+
if len(signature.params) != len(c_sig):
318+
exit_with_error('EM_JS functions with 64-bit arguments requires WASM_BIGINT to be enabled: `%s` (%s, %s)', em_js_func, c_sig, signature.params)
319+
302320
if settings.SIDE_MODULE:
303321
if metadata['asmConsts']:
304322
exit_with_error('EM_ASM is not supported in side modules')

tests/core/test_em_js_i64.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <stdint.h>
2+
#include <emscripten.h>
3+
4+
EM_JS(void, foo, (uint64_t a, int64_t b), {
5+
console.log('a:' + a);
6+
console.log('b:' + b);
7+
})
8+
9+
int main() {
10+
foo(42000000000ull, -42ll);
11+
}

tests/core/test_em_js_i64.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
a:42000000000
2+
b:-42

tests/test_core.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2142,6 +2142,14 @@ def test_em_js(self, args, force_c):
21422142
self.do_core_test('test_em_js.cpp', force_c=force_c)
21432143
self.assertContained("no args returning int", read_file('test_em_js.js'))
21442144

2145+
def test_em_js_i64(self):
2146+
err = self.expect_fail([EMCC, test_file('core/test_em_js_i64.c')])
2147+
self.assertContained('emcc: error: EM_JS functions with 64-bit arguments requires WASM_BIGINT to be enabled: `foo`', err)
2148+
2149+
self.set_setting('WASM_BIGINT')
2150+
self.node_args += ['--experimental-wasm-bigint']
2151+
self.do_core_test('test_em_js_i64.c')
2152+
21452153
def test_runtime_stacksave(self):
21462154
self.do_runf(test_file('core/test_runtime_stacksave.c'), 'success')
21472155

tools/webassembly.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,14 @@ class InvalidWasmError(BaseException):
114114

115115
Section = namedtuple('Section', ['type', 'size', 'offset', 'name'])
116116
Limits = namedtuple('Limits', ['flags', 'initial', 'maximum'])
117-
Import = namedtuple('Import', ['kind', 'module', 'field'])
117+
Import = namedtuple('Import', ['kind', 'module', 'field', 'type'])
118118
Export = namedtuple('Export', ['name', 'kind', 'index'])
119119
Global = namedtuple('Global', ['type', 'mutable', 'init'])
120120
Dylink = namedtuple('Dylink', ['mem_size', 'mem_align', 'table_size', 'table_align', 'needed', 'export_info', 'import_info'])
121121
Table = namedtuple('Table', ['elem_type', 'limits'])
122122
FunctionBody = namedtuple('FunctionBody', ['offset', 'size'])
123123
DataSegment = namedtuple('DataSegment', ['flags', 'init', 'offset', 'size'])
124+
FuncType = namedtuple('FuncType', ['params', 'returns'])
124125

125126

126127
class Module:
@@ -210,6 +211,27 @@ def sections(self):
210211
yield Section(section_type, section_size, section_offset, name)
211212
offset = section_offset + section_size
212213

214+
def get_types(self):
215+
type_section = self.get_section(SecType.TYPE)
216+
if not type_section:
217+
return []
218+
self.seek(type_section.offset)
219+
num_types = self.readULEB()
220+
types = []
221+
for i in range(num_types):
222+
params = []
223+
returns = []
224+
type_form = self.readByte()
225+
assert type_form == 0x60
226+
num_params = self.readULEB()
227+
for j in range(num_params):
228+
params.append(self.read_type())
229+
num_returns = self.readULEB()
230+
for j in range(num_returns):
231+
returns.append(self.read_type())
232+
types.append(FuncType(params, returns))
233+
return types
234+
213235
def parse_features_section(self):
214236
features = []
215237
sec = self.get_custom_section('target_features')
@@ -315,22 +337,23 @@ def get_imports(self):
315337
mod = self.readString()
316338
field = self.readString()
317339
kind = ExternType(self.readByte())
318-
imports.append(Import(kind, mod, field))
340+
type_ = None
319341
if kind == ExternType.FUNC:
320-
self.readULEB() # sig
342+
type_ = self.readULEB()
321343
elif kind == ExternType.GLOBAL:
322-
self.readSLEB() # global type
344+
type_ = self.readSLEB()
323345
self.readByte() # mutable
324346
elif kind == ExternType.MEMORY:
325347
self.read_limits() # limits
326348
elif kind == ExternType.TABLE:
327-
self.readSLEB() # table type
349+
type_ = self.readSLEB()
328350
self.read_limits() # limits
329351
elif kind == ExternType.TAG:
330352
self.readByte() # attribute
331-
self.readULEB() # sig
353+
type_ = self.readULEB()
332354
else:
333355
assert False
356+
imports.append(Import(kind, mod, field, type_))
334357

335358
return imports
336359

0 commit comments

Comments
 (0)