diff --git a/emcc.py b/emcc.py index 6b59abb129318..b2364bd121219 100755 --- a/emcc.py +++ b/emcc.py @@ -1724,6 +1724,9 @@ def phase_linker_setup(options, state, newargs, user_settings): assert not settings.EXPORTED_FUNCTIONS settings.EXPORTED_FUNCTIONS = ['_main'] + if '_main' in settings.EXPORTED_FUNCTIONS: + settings.EXPORTED_FUNCTIONS.append('___main_argc_argv') + if settings.STANDALONE_WASM: # In STANDALONE_WASM mode we either build a command or a reactor. # See https://github.com/WebAssembly/WASI/blob/main/design/application-abi.md diff --git a/emscripten.py b/emscripten.py index 3200163b6a3fc..5e31a89b8ba67 100644 --- a/emscripten.py +++ b/emscripten.py @@ -297,6 +297,11 @@ def emscript(in_wasm, out_wasm, outfile_js, memfile): metadata = finalize_wasm(in_wasm, out_wasm, memfile) + if '__main_argc_argv' in metadata['exports']: + settings.MANGLED_MAIN = 1 + metadata['exports'].remove('__main_argc_argv') + metadata['exports'].append('main') + update_settings_glue(metadata) if not settings.WASM_BIGINT and metadata['emJsFuncs']: @@ -778,6 +783,8 @@ def make_export_wrappers(exports, delay_assignment): wrappers = [] for name in exports: mangled = asmjs_mangle(name) + if settings.MANGLED_MAIN and name == 'main': + name = '__main_argc_argv' # The emscripten stack functions are called very early (by writeStackCookie) before # the runtime is initialized so we can't create these wrappers that check for # runtimeInitialized. @@ -817,8 +824,6 @@ def create_receiving(exports): if not settings.DECLARE_ASM_MODULE_EXPORTS: return '' - exports_that_are_not_initializers = [x for x in exports if x != building.WASM_CALL_CTORS] - receiving = [] # with WASM_ASYNC_COMPILATION that asm object may not exist at this point in time @@ -833,8 +838,12 @@ def create_receiving(exports): # var asm = output.instance.exports; # _main = asm["_main"]; generate_dyncall_assignment = settings.DYNCALLS and '$dynCall' in settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE + exports_that_are_not_initializers = [x for x in exports if x != building.WASM_CALL_CTORS] + for s in exports_that_are_not_initializers: mangled = asmjs_mangle(s) + if settings.MANGLED_MAIN and s == 'main': + s = '__main_argc_argv' dynCallAssignment = ('dynCalls["' + s.replace('dynCall_', '') + '"] = ') if generate_dyncall_assignment and mangled.startswith('dynCall_') else '' receiving += [dynCallAssignment + mangled + ' = asm["' + s + '"];'] else: diff --git a/src/library_dylink.js b/src/library_dylink.js index 011b2e569fe7e..3305e9944f9c0 100644 --- a/src/library_dylink.js +++ b/src/library_dylink.js @@ -444,7 +444,7 @@ var LibraryDylink = { // Export native export on the Module object. // TODO(sbc): Do all users want this? Should we skip this by default? - var module_sym = asmjsMangle(sym); + var module_sym = asmjsMangle(sym == '__main_argc_argv' ? 'main' : sym); if (!Module.hasOwnProperty(module_sym)) { Module[module_sym] = exports[sym]; } diff --git a/src/settings_internal.js b/src/settings_internal.js index c7dab30c6ede6..c9d42d29cb5ca 100644 --- a/src/settings_internal.js +++ b/src/settings_internal.js @@ -227,3 +227,5 @@ var TRANSPILE_TO_ES5 = false; // A copy of the default the default INCOMING_MODULE_JS_API. (Soon to // include additional items). var ALL_INCOMING_MODULE_JS_API = [] + +var MANGLED_MAIN = false; diff --git a/system/lib/standalone/__main_argc_argv.c b/system/lib/standalone/__main_argc_argv.c index d56f532540177..f940dfc8907aa 100644 --- a/system/lib/standalone/__main_argc_argv.c +++ b/system/lib/standalone/__main_argc_argv.c @@ -5,17 +5,13 @@ * found in the LICENSE file. */ -// This file should no longer be needed once we land the llvm-side change to -// switch to using __main_argc_argv: -// TODO(https://reviews.llvm.org/D75277) - -// See https://github.com/CraneStation/wasi-libc/pull/152 - -#include - -int main(int argc, char *argv[]); +// New compilers define `__main_argc_argv`. If that doesn't exist, we +// may get called here. Old compilers define `main` expecting an +// argv/argc, so call that. +// TODO: Remove this layer when we no longer have to support old compilers. +int __legacy_main(int argc, char *argv[]) __asm("main"); __attribute__((__weak__)) int __main_argc_argv(int argc, char *argv[]) { - return main(argc, argv); + return __legacy_main(argc, argv); } diff --git a/tools/building.py b/tools/building.py index 71b8b11b3e816..aeb7e1f4cbd55 100644 --- a/tools/building.py +++ b/tools/building.py @@ -233,7 +233,7 @@ def llvm_backend_args(): # When 'main' has a non-standard signature, LLVM outlines its content out to # '__original_main'. So we add it to the allowed list as well. if 'main' in settings.EXCEPTION_CATCHING_ALLOWED: - settings.EXCEPTION_CATCHING_ALLOWED += ['__original_main'] + settings.EXCEPTION_CATCHING_ALLOWED += ['__original_main', '__main_argc_argv'] allowed = ','.join(settings.EXCEPTION_CATCHING_ALLOWED) args += ['-emscripten-cxx-exceptions-allowed=' + allowed]