Skip to content
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
19 changes: 19 additions & 0 deletions emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,25 @@ def emscript(in_wasm, out_wasm, outfile_js, memfile):

update_settings_glue(metadata)

if not settings.WASM_BIGINT and metadata['emJsFuncs']:
module = webassembly.Module(in_wasm)
types = module.get_types()
import_map = {}
for imp in module.get_imports():
import_map[imp.field] = imp
for em_js_func, raw in metadata.get('emJsFuncs', {}).items():
c_sig = raw.split('<::>')[0].strip('()')
if not c_sig or c_sig == 'void':
c_sig = []
else:
c_sig = c_sig.split(',')
if em_js_func in import_map:
imp = import_map[em_js_func]
assert(imp.kind == webassembly.ExternType.FUNC)
signature = types[imp.type]
if len(signature.params) != len(c_sig):
diagnostics.warning('em-js-i64', 'using 64-bit arguments in EM_JS function without WASM_BIGINT is not yet fully supported: `%s` (%s, %s)', em_js_func, c_sig, signature.params)

if settings.SIDE_MODULE:
if metadata['asmConsts']:
exit_with_error('EM_ASM is not supported in side modules')
Expand Down
14 changes: 14 additions & 0 deletions tests/core/test_em_js_i64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <stdint.h>
#include <emscripten.h>

EM_JS(void, foo, (uint64_t a, int64_t b), {
console.log(typeof a);
console.log(typeof b);

console.log('a:' + a);
console.log('b:' + b);
})

int main() {
foo(42000000000ull, -42ll);
}
2 changes: 2 additions & 0 deletions tests/core/test_em_js_i64.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
a:42000000000
b:-42
9 changes: 9 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2142,6 +2142,15 @@ def test_em_js(self, args, force_c):
self.do_core_test('test_em_js.cpp', force_c=force_c)
self.assertContained("no args returning int", read_file('test_em_js.js'))

@no_wasm2js('WASM_BIGINT is not compatible with wasm2js')
def test_em_js_i64(self):
err = self.expect_fail([EMCC, '-Werror', test_file('core/test_em_js_i64.c')])
self.assertContained('emcc: error: using 64-bit arguments in EM_JS function without WASM_BIGINT is not yet fully supported: `foo`', err)

self.set_setting('WASM_BIGINT')
self.node_args += ['--experimental-wasm-bigint']
self.do_core_test('test_em_js_i64.c')

def test_runtime_stacksave(self):
self.do_runf(test_file('core/test_runtime_stacksave.c'), 'success')

Expand Down
11 changes: 7 additions & 4 deletions tools/extract_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,6 @@ def extract_metadata(filename):

for i in imports:
if i.kind == webassembly.ExternType.FUNC:
if i.field.startswith('invoke_'):
invoke_funcs.append(i.field)
elif i.field not in em_js_funcs:
declares.append(i.field)
imported_funcs += 1
elif i.kind == webassembly.ExternType.GLOBAL:
imported_globals += 1
Expand All @@ -194,6 +190,13 @@ def extract_metadata(filename):
string_address = get_global_value(globl)
em_js_funcs[name] = get_string_at(module, string_address)

for i in imports:
if i.kind == webassembly.ExternType.FUNC:
if i.field.startswith('invoke_'):
invoke_funcs.append(i.field)
elif i.field not in em_js_funcs:
declares.append(i.field)

export_names = [e.name for e in exports if e.kind == webassembly.ExternType.FUNC]

features = module.parse_features_section()
Expand Down
1 change: 1 addition & 0 deletions tools/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
diagnostics.add_warning('pthreads-mem-growth')
diagnostics.add_warning('transpile')
diagnostics.add_warning('limited-postlink-optimizations')
diagnostics.add_warning('em-js-i64')


# TODO(sbc): Investigate switching to shlex.quote
Expand Down
35 changes: 29 additions & 6 deletions tools/webassembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,14 @@ class InvalidWasmError(BaseException):

Section = namedtuple('Section', ['type', 'size', 'offset', 'name'])
Limits = namedtuple('Limits', ['flags', 'initial', 'maximum'])
Import = namedtuple('Import', ['kind', 'module', 'field'])
Import = namedtuple('Import', ['kind', 'module', 'field', 'type'])
Export = namedtuple('Export', ['name', 'kind', 'index'])
Global = namedtuple('Global', ['type', 'mutable', 'init'])
Dylink = namedtuple('Dylink', ['mem_size', 'mem_align', 'table_size', 'table_align', 'needed', 'export_info', 'import_info'])
Table = namedtuple('Table', ['elem_type', 'limits'])
FunctionBody = namedtuple('FunctionBody', ['offset', 'size'])
DataSegment = namedtuple('DataSegment', ['flags', 'init', 'offset', 'size'])
FuncType = namedtuple('FuncType', ['params', 'returns'])


class Module:
Expand Down Expand Up @@ -210,6 +211,27 @@ def sections(self):
yield Section(section_type, section_size, section_offset, name)
offset = section_offset + section_size

def get_types(self):
type_section = self.get_section(SecType.TYPE)
if not type_section:
return []
self.seek(type_section.offset)
num_types = self.readULEB()
types = []
for i in range(num_types):
params = []
returns = []
type_form = self.readByte()
assert type_form == 0x60
num_params = self.readULEB()
for j in range(num_params):
params.append(self.read_type())
num_returns = self.readULEB()
for j in range(num_returns):
returns.append(self.read_type())
types.append(FuncType(params, returns))
return types

def parse_features_section(self):
features = []
sec = self.get_custom_section('target_features')
Expand Down Expand Up @@ -315,22 +337,23 @@ def get_imports(self):
mod = self.readString()
field = self.readString()
kind = ExternType(self.readByte())
imports.append(Import(kind, mod, field))
type_ = None
if kind == ExternType.FUNC:
self.readULEB() # sig
type_ = self.readULEB()
elif kind == ExternType.GLOBAL:
self.readSLEB() # global type
type_ = self.readSLEB()
self.readByte() # mutable
elif kind == ExternType.MEMORY:
self.read_limits() # limits
elif kind == ExternType.TABLE:
self.readSLEB() # table type
type_ = self.readSLEB()
self.read_limits() # limits
elif kind == ExternType.TAG:
self.readByte() # attribute
self.readULEB() # sig
type_ = self.readULEB()
else:
assert False
imports.append(Import(kind, mod, field, type_))

return imports

Expand Down