Skip to content

Commit

Permalink
[EH]
Browse files Browse the repository at this point in the history
  • Loading branch information
aheejin committed May 7, 2024
1 parent 80798ac commit d923aa8
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 12 deletions.
3 changes: 3 additions & 0 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,9 @@ def phase_setup(options, state, newargs):
if settings.DISABLE_EXCEPTION_THROWING and not settings.DISABLE_EXCEPTION_CATCHING:
exit_with_error("DISABLE_EXCEPTION_THROWING was set (probably from -fno-exceptions) but is not compatible with enabling exception catching (DISABLE_EXCEPTION_CATCHING=0). If you don't want exceptions, set DISABLE_EXCEPTION_CATCHING to 1; if you do want exceptions, don't link with -fno-exceptions")

if user_settings.get('EXPERIMENTAL_NEW_WASM_EXCEPTIONS') == '1' and not settings.WASM_EXCEPTIONS:
exit_with_error('EXPERIMENTAL_NEW_WASM_EXCEPTIONS requires -fwasm-exceptions')

if options.target.startswith('wasm64'):
default_setting('MEMORY64', 1)

Expand Down
6 changes: 6 additions & 0 deletions src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,12 @@ var EXPORT_EXCEPTION_HANDLING_HELPERS = false;
// [link]
var EXCEPTION_STACK_TRACES = false;

// Emit instructions for the new Wasm exception handling proposal, which was
// adopted on Oct 2023. The implementation of the new proposal is still in
// progress and this feature is currently experimental.
// [compile+link]
var EXPERIMENTAL_NEW_WASM_EXCEPTIONS = false;

// Emscripten throws an ExitStatus exception to unwind when exit() is called.
// Without this setting enabled this can show up as a top level unhandled
// exception.
Expand Down
66 changes: 54 additions & 12 deletions test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,16 @@ def decorated(self, *args, **kwargs):
return decorated


def requires_new_wasm_eh(func):
assert callable(func)

def decorated(self, *args, **kwargs):
self.require_new_wasm_eh()
return func(self, *args, **kwargs)

return decorated


def requires_v8(func):
assert callable(func)

Expand Down Expand Up @@ -500,24 +510,29 @@ def metafunc(self, standalone):


# Tests exception handling / setjmp/longjmp handling in Emscripten EH/SjLj mode
# and if possible, new wasm EH/SjLj mode. This tests two combinations:
# and new wasm EH/SjLj modes. This tests three combinations:
# - Emscripten EH + Emscripten SjLj
# - Wasm EH + Wasm SjLj
# - Wasm EH + Wasm SjLj (Phase 3, to be deprecated)
# - Wasm EH _ Wasm SjLj (New, experimental)
def with_all_eh_sjlj(f):
assert callable(f)

@wraps(f)
def metafunc(self, is_native, *args, **kwargs):
if is_native:
def metafunc(self, mode, *args, **kwargs):
if mode == 'wasm' or mode == 'new_wasm':
# Wasm EH is currently supported only in wasm backend and V8
if self.is_wasm2js():
self.skipTest('wasm2js does not support wasm EH/SjLj')
self.require_wasm_eh()
# FIXME Temporarily disabled. Enable this later when the bug is fixed.
if '-fsanitize=address' in self.emcc_args:
self.skipTest('Wasm EH does not work with asan yet')
self.emcc_args.append('-fwasm-exceptions')
self.set_setting('SUPPORT_LONGJMP', 'wasm')
if mode == 'wasm':
self.require_wasm_eh()
if mode == 'new_wasm':
self.require_new_wasm_eh()
self.set_setting('EXPERIMENTAL_NEW_WASM_EXCEPTIONS')
f(self, *args, **kwargs)
else:
self.set_setting('DISABLE_EXCEPTION_CATCHING', 0)
Expand All @@ -529,8 +544,9 @@ def metafunc(self, is_native, *args, **kwargs):
self.set_setting('DEFAULT_TO_CXX')
f(self, *args, **kwargs)

parameterize(metafunc, {'': (False,),
'wasm': (True,)})
parameterize(metafunc, {'emscripten': ('emscripten',),
'wasm': ('wasm',),
'new_wasm': ('new_wasm',)})
return metafunc


Expand All @@ -540,22 +556,27 @@ def with_all_sjlj(f):
assert callable(f)

@wraps(f)
def metafunc(self, is_native):
if is_native:
def metafunc(self, mode):
if mode == 'wasm' or mode == 'new_wasm':
if self.is_wasm2js():
self.skipTest('wasm2js does not support wasm SjLj')
self.require_wasm_eh()
# FIXME Temporarily disabled. Enable this later when the bug is fixed.
if '-fsanitize=address' in self.emcc_args:
self.skipTest('Wasm EH does not work with asan yet')
self.set_setting('SUPPORT_LONGJMP', 'wasm')
if mode == 'wasm':
self.require_wasm_eh()
if mode == 'new_wasm':
self.require_new_wasm_eh()
self.set_setting('EXPERIMENTAL_NEW_WASM_EXCEPTIONS')
f(self)
else:
self.set_setting('SUPPORT_LONGJMP', 'emscripten')
f(self)

parameterize(metafunc, {'': (False,),
'wasm': (True,)})
parameterize(metafunc, {'emscripten': ('emscripten',),
'wasm': ('wasm',),
'new_wasm': ('new_wasm',)})
return metafunc


Expand Down Expand Up @@ -877,6 +898,27 @@ def require_wasm_eh(self):
else:
self.fail('either d8 or node >= 17 required to run wasm-eh tests. Use EMTEST_SKIP_EH to skip')

def require_new_wasm_eh(self):
nodejs = self.get_nodejs()
if nodejs:
version = shared.get_node_version(nodejs)
if version >= (22, 0, 0):
self.js_engines = [nodejs]
self.node_args.append('--experimental-wasm-exnref')
return

if config.V8_ENGINE and config.V8_ENGINE in self.js_engines:
self.emcc_args.append('-sENVIRONMENT=shell')
# TODO version
self.js_engines = [config.V8_ENGINE]
self.v8_args.append('--experimental-wasm-exnref')
return

if 'EMTEST_SKIP_EH' in os.environ:
self.skipTest('test requires d8 >= ??? (and EMTEST_SKIP_EH is set)')
else:
self.fail('either d8 >= ??? required to run wasm-eh tests. Use EMTEST_SKIP_EH to skip')

def require_jspi(self):
# emcc warns about stack switching being experimental, and we build with
# warnings-as-errors, so disable that warning
Expand Down
1 change: 1 addition & 0 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1557,6 +1557,7 @@ def clear_all_relevant_settings(self):
self.clear_setting('DISABLE_EXCEPTION_CATCHING')
self.clear_setting('SUPPORT_LONGJMP')
self.clear_setting('ASYNCIFY')
self.clear_setting('EXPERIMENTAL_NEW_WASM_EXCEPTIONS')

# Emscripten EH and Wasm EH cannot be enabled at the same time
self.set_setting('DISABLE_EXCEPTION_CATCHING', 0)
Expand Down
3 changes: 3 additions & 0 deletions tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,9 @@ def check_human_readable_list(items):
extras = settings.BINARYEN_EXTRA_PASSES.split(',')
passes += [('--' + p) if p[0] != '-' else p for p in extras if p]

if settings.EXPERIMENTAL_NEW_WASM_EXCEPTIONS:
passes += ['--experimental-new-eh']

return passes


Expand Down

0 comments on commit d923aa8

Please sign in to comment.