diff --git a/emscripten.py b/emscripten.py index 32f74199295b8..d41b6d71da984 100644 --- a/emscripten.py +++ b/emscripten.py @@ -2206,8 +2206,25 @@ def emscript_wasm_backend(infile, outfile, memfile, compiler_engine, # * Run wasm-emscripten-finalize to extract metadata and modify the binary # to use emscripten's wasm<->JS ABI # * Use the metadata to generate the JS glue that goes with the wasm + if shared.Settings.MAIN_MODULE: + # Run compile_settings here to retrieve all the JS library functions. + # Unfortunately, we need to run it later again to capture the exported functions + # from the Wasm + glue, forwarded_data = compile_settings(compiler_engine, temp_files) + forwarded_json = json.loads(forwarded_data) + library_fns = forwarded_json['Functions']['libraryFunctions'] + library_fns_list = [] + for name in library_fns: + library_fns_list.append(name) + + js_symbols = infile + '.js_symbols' + with open(js_symbols, 'w') as js_symbols_file: + for sym in library_fns_list: + js_symbols_file.write(sym + '\n') + else: + js_symbols = [] - metadata = finalize_wasm(temp_files, infile, outfile, memfile, DEBUG) + metadata = finalize_wasm(temp_files, infile, outfile, memfile, DEBUG, js_symbols) update_settings_glue(metadata, DEBUG) @@ -2318,7 +2335,7 @@ def remove_trailing_zeros(memfile): f.write(mem_data[:end]) -def finalize_wasm(temp_files, infile, outfile, memfile, DEBUG): +def finalize_wasm(temp_files, infile, outfile, memfile, DEBUG, libraryfile): basename = shared.unsuffixed(outfile.name) wasm = basename + '.wasm' base_wasm = infile @@ -2365,6 +2382,9 @@ def finalize_wasm(temp_files, infile, outfile, memfile, DEBUG): args.append('--pass-arg=legalize-js-interface-export-originals') if shared.Settings.FULL_DWARF: args.append('--dwarf') + + if shared.Settings.MAIN_MODULE and libraryfile: + args.append('--pass-arg=js-symbols@%s' % libraryfile) stdout = shared.Building.run_binaryen_command('wasm-emscripten-finalize', infile=base_wasm, outfile=wasm, diff --git a/tests/test_core.py b/tests/test_core.py index a2c074a461cea..7f87b6870780c 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -8559,6 +8559,41 @@ def test_safe_stack_dylink(self): } ''', ['abort(stack overflow)', '__handle_stack_overflow'], assert_returncode=None) + @no_fastcomp('WASM backend convert imports to indirect calls') + @needs_dlfcn + def test_dylink_imports_to_indirect_calls(self): + # The ImportsToIndirectCalls pass in Binaryen should not allocate a new fp$ for + # imports that are already address taken. Test out both cases whereby the imports + # are either used directly or thru its address. + self.set_setting('EXIT_RUNTIME', 1) + self.dylink_test(main=r''' + #include + extern int sidey(); + extern int sidey2(); + typedef int (*func)(); + int mainy() { + return 19; + } + + int main(int argc, char **argv) { + sidey(); + func funcPtr = (0 == argc) ? sidey:sidey2; + funcPtr(); + return 0; + } + ''', side=r''' + #include + int sidey() { + printf("sidey says %d ", 17); + return 17; + } + + int sidey2() { + printf("sidey2 says %d", 18); + return 18; + } + ''', expected='sidey says 17 sidey2 says 18', need_reverse=False) + @also_with_standalone_wasm def test_undefined_main(self): # By default in emscripten we allow main to be undefined. Its used when