Skip to content

Commit fcfa4d8

Browse files
authored
STANDALONE_WASM: separate crt1 for commands and reactors (#11167)
Unlike without STANDALONE_WASM users are expected to either define a main or explicitly opt out. This change and paves to way to moving to llvm's new main mangling method: https://reviews.llvm.org/D70700 Fixes: #9640
1 parent 6511178 commit fcfa4d8

13 files changed

+64
-35
lines changed

src/modules.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ var LibraryManager = {
161161
}
162162

163163
if (BOOTSTRAPPING_STRUCT_INFO) {
164-
libraries = ['library_formatString.js'];
164+
libraries = ['library_formatString.js', 'library_stack_trace.js'];
165165
}
166166

167167
// Deduplicate libraries to avoid processing any library file multiple times

src/postamble.js

+4
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ function callMain(args) {
156156
#endif
157157

158158
#if STANDALONE_WASM
159+
#if EXPECT_MAIN
159160
var entryFunction = Module['__start'];
161+
#else
162+
var entryFunction = Module['__initialize'];
163+
#endif
160164
#else
161165
var entryFunction = Module['_main'];
162166
#endif

system/lib/libc/crt1.c

+1-7
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717

1818
extern void __wasm_call_ctors(void) __attribute__((weak));
1919

20-
// TODO(sbc): We shouldn't even link this file if there is no main:
21-
// https://github.com/emscripten-core/emscripten/issues/9640
22-
extern int main(int argc, char** argv) __attribute__((weak));
20+
extern int main(int argc, char** argv);
2321

2422
// If main() uses argc/argv, then no __original_main is emitted, and then
2523
// this definition is used, which loads those values and sends them to main.
@@ -66,10 +64,6 @@ void _start(void) {
6664
__wasm_call_ctors();
6765
}
6866

69-
if (!main) {
70-
return;
71-
}
72-
7367
int r = __original_main();
7468

7569
exit(r);

system/lib/libc/crt1_reactor.c

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright 2020 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
extern void __wasm_call_ctors(void) __attribute__((weak));
9+
10+
void _initialize(void) {
11+
if (__wasm_call_ctors) {
12+
__wasm_call_ctors();
13+
}
14+
}

tests/other/metadce/mem_no_main_O3_STANDALONE_WASM.exports

-3
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
_initialize
2+
foo
3+
memory

tests/test_core.py

+13-20
Original file line numberDiff line numberDiff line change
@@ -1595,7 +1595,9 @@ def test_iostream_ctors(self):
15951595
}
15961596
''', 'bugfree code')
15971597

1598-
@also_with_standalone_wasm
1598+
# Marked as impure since the WASI reactor modules (modules without main)
1599+
# are not yet suppored by the wasm engines we test against.
1600+
@also_with_impure_standalone_wasm
15991601
def test_ctors_no_main(self):
16001602
self.emcc_args.append('--no-entry')
16011603
self.do_run_in_out_file_test('tests', 'core', 'test_ctors_no_main')
@@ -8852,22 +8854,6 @@ def test_safe_stack_dylink(self):
88528854
}
88538855
''', ['abort(stack overflow)', '__handle_stack_overflow'], assert_returncode=None)
88548856

8855-
@also_with_standalone_wasm
8856-
def test_undefined_main(self):
8857-
if self.get_setting('LLD_REPORT_UNDEFINED'):
8858-
self.skipTest('LLD_REPORT_UNDEFINED does not allow implicit undefined main')
8859-
if self.get_setting('STRICT'):
8860-
self.skipTest('STRICT does not allow implicit undefined main')
8861-
# By default in emscripten we allow main to be undefined. Its used when
8862-
# building library code that has no main.
8863-
# TODO(sbc): Simplify the code by making this an opt-in feature.
8864-
# https://github.com/emscripten-core/emscripten/issues/9640
8865-
src = '''
8866-
#include <emscripten.h>
8867-
EMSCRIPTEN_KEEPALIVE void foo() {}
8868-
'''
8869-
self.build(src, self.get_dir(), 'test.c')
8870-
88718857
def test_fpic_static(self):
88728858
self.emcc_args.append('-fPIC')
88738859
self.do_run_in_out_file_test('tests', 'core', 'test_hello_world')
@@ -8909,16 +8895,23 @@ def test_minimal_runtime_emscripten_get_exported_function(self):
89098895
self.emcc_args += ['-lexports.js', '-s', 'MINIMAL_RUNTIME=1']
89108896
self.do_run_in_out_file_test('tests', 'core', 'test_get_exported_function')
89118897

8912-
def test_auto_detect_main(self):
8913-
if not self.get_setting('LLD_REPORT_UNDEFINED') and not self.get_setting('STRICT'):
8898+
# Marked as impure since the WASI reactor modules (modules without main)
8899+
# are not yet suppored by the wasm engines we test against.
8900+
@also_with_impure_standalone_wasm
8901+
def test_undefined_main(self):
8902+
# Traditionally in emscripten we allow main to be undefined. This allows programs with a main
8903+
# and libraries without a main to be compiled identically.
8904+
# However we are trying to move away from that model to a more explicit opt-out model. See:
8905+
# https://github.com/emscripten-core/emscripten/issues/9640
8906+
if not self.get_setting('LLD_REPORT_UNDEFINED') and not self.get_setting('STRICT') and not self.get_setting('STANDALONE_WASM'):
89148907
self.do_run_in_out_file_test('tests', 'core', 'test_ctors_no_main')
89158908

89168909
# Disabling IGNORE_MISSING_MAIN should cause link to fail due to missing main
89178910
self.set_setting('IGNORE_MISSING_MAIN', 0)
89188911
err = self.expect_fail([PYTHON, EMCC, path_from_root('tests', 'core', 'test_ctors_no_main.cpp')] + self.get_emcc_args())
89198912
self.assertContained('error: entry symbol not defined (pass --no-entry to suppress): main', err)
89208913

8921-
# We can fix the error either by adding --no-entry or by setting EXPORTED_FUNCTIONS to empty
8914+
# If we pass --no-entry or set EXPORTED_FUNCTIONS to empty should never see any errors
89228915
self.emcc_args.append('--no-entry')
89238916
self.do_run_in_out_file_test('tests', 'core', 'test_ctors_no_main')
89248917

tests/test_other.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8379,7 +8379,7 @@ def test_metadce_hello_fastcomp(self, *args):
83798379
'O3_standalone_narg': ('mem_no_argv.c', ['-O3', '-s', 'STANDALONE_WASM'],
83808380
[], [], 6309), # noqa
83818381
# without main, no support code for argc/argv is emitted either
8382-
'O3_standalone_lib': ('mem_no_main.c', ['-O3', '-s', 'STANDALONE_WASM'],
8382+
'O3_standalone_lib': ('mem_no_main.c', ['-O3', '-s', 'STANDALONE_WASM', '--no-entry'],
83838383
[], [], 6309), # noqa
83848384
# Growth support code is in JS, no significant change in the wasm
83858385
'O3_grow': ('mem.c', ['-O3', '-s', 'ALLOW_MEMORY_GROWTH'],

tools/shared.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1582,9 +1582,12 @@ def lld_flags_for_executable(external_symbol_list):
15821582
'-z', 'stack-size=%s' % Settings.TOTAL_STACK,
15831583
'--initial-memory=%d' % Settings.INITIAL_MEMORY,
15841584
]
1585-
use_start_function = Settings.STANDALONE_WASM
15861585

1587-
if not use_start_function:
1586+
if Settings.STANDALONE_WASM:
1587+
# when Settings.EXPECT_MAIN is set we fall back to wasm-ld default of _start
1588+
if not Settings.EXPECT_MAIN:
1589+
cmd += ['--entry=_initialize']
1590+
else:
15881591
if Settings.EXPECT_MAIN and not Settings.IGNORE_MISSING_MAIN:
15891592
cmd += ['--entry=main']
15901593
else:

tools/system_libs.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,24 @@ def can_build(self):
884884
return super(crt1, self).can_build() and shared.Settings.WASM_BACKEND
885885

886886

887+
class crt1_reactor(MuslInternalLibrary):
888+
name = 'crt1_reactor'
889+
cflags = ['-O2']
890+
src_dir = ['system', 'lib', 'libc']
891+
src_files = ['crt1_reactor.c']
892+
893+
force_object_files = True
894+
895+
def get_ext(self):
896+
return '.o'
897+
898+
def can_use(self):
899+
return super(crt1_reactor, self).can_use() and shared.Settings.STANDALONE_WASM
900+
901+
def can_build(self):
902+
return super(crt1_reactor, self).can_build() and shared.Settings.WASM_BACKEND
903+
904+
887905
class libc_extras(NoBCLibrary, MuslInternalLibrary):
888906
"""This library is separate from libc itself for fastcomp only so that the
889907
constructor it contains can be DCE'd. Such tricks are not needed wih the
@@ -1557,7 +1575,10 @@ def add_library(lib):
15571575
libs_to_link.append((lib.get_path(), need_whole_archive))
15581576

15591577
if shared.Settings.STANDALONE_WASM:
1560-
add_library(system_libs_map['crt1'])
1578+
if shared.Settings.EXPECT_MAIN:
1579+
add_library(system_libs_map['crt1'])
1580+
else:
1581+
add_library(system_libs_map['crt1_reactor'])
15611582

15621583
for forced in force_include:
15631584
add_library(system_libs_map[forced])

0 commit comments

Comments
 (0)