From 4e299a2113db066cf90791fd9234074579cad4ac Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 6 Sep 2022 04:55:38 -0700 Subject: [PATCH] [Wasm64] Run core tests under wamm64 as well as wasm64l --- .circleci/config.yml | 5 ++- emcc.py | 2 ++ src/library_wasi.js | 2 +- test/common.py | 18 ++++++++-- test/core/test_main_reads_args.out | 2 +- test/minimal_runtime_exit_handling.js | 36 ++++++++++--------- test/test_core.py | 51 +++++++++++++++++++++------ 7 files changed, 82 insertions(+), 34 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bd1284ecf6e32..7f003ebdd0b8a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -449,7 +449,10 @@ jobs: steps: - run-tests-linux: frozen_cache: false - test_targets: "wasm64.test_hello_world wasm64.test_ccall wasm64l" + test_targets: "wasm64" + - run-tests-linux: + frozen_cache: false + test_targets: "wasm64l" test-other: executor: bionic steps: diff --git a/emcc.py b/emcc.py index eccb7932f0bb9..4b95581d3545b 100755 --- a/emcc.py +++ b/emcc.py @@ -2334,6 +2334,8 @@ def check_memory_setting(setting): if settings.MEMORY64: if settings.RELOCATABLE: exit_with_error('MEMORY64 is not compatible with dynamic linking') + if settings.ASYNCIFY and settings.MEMORY64 == 1: + exit_with_error('MEMORY64=1 is not compatible with ASYNCIFY') if not settings.DISABLE_EXCEPTION_CATCHING: exit_with_error('MEMORY64 is not compatible with DISABLE_EXCEPTION_CATCHING=0') settings.WASM_BIGINT = 1 diff --git a/src/library_wasi.js b/src/library_wasi.js index 048f995f0d53c..33bea5a12796a 100644 --- a/src/library_wasi.js +++ b/src/library_wasi.js @@ -35,7 +35,7 @@ var WasiLibrary = { ABORT = true; } quit_(code, new ExitStatus(code)); -#endif +#endif // MINIMAL_RUNTIME }, $getEnvStrings__deps: ['$ENV', '$getExecutableName'], diff --git a/test/common.py b/test/common.py index b4155c37ed334..ca9ad37838b09 100644 --- a/test/common.py +++ b/test/common.py @@ -459,6 +459,15 @@ def require_node(self): self.skipTest("MEMORY64=1 tests don't yet run under node") self.js_engines = [config.NODE_JS] + def have_node(self): + """Return true if node is available, False otherwise. + + If node is availavle it is set as only engine for the rest of the test.""" + if config.NODE_JS not in config.JS_ENGINES: + return False + self.js_engines == [config.NODE_JS] + return True + def setup_node_pthreads(self): self.require_node() self.set_setting('USE_PTHREADS') @@ -616,15 +625,18 @@ def in_dir(self, *pathelems): return os.path.join(self.get_dir(), *pathelems) def add_pre_run(self, code): - create_file('prerun.js', 'Module.preRun = function() { %s }' % code) + assert not self.get_setting('MINIMAL_RUNTIME') + create_file('prerun.js', 'Module.preRun = function() { %s }\n' % code) self.emcc_args += ['--pre-js', 'prerun.js'] def add_post_run(self, code): - create_file('postrun.js', 'Module.postRun = function() { %s }' % code) + assert not self.get_setting('MINIMAL_RUNTIME') + create_file('postrun.js', 'Module.postRun = function() { %s }\n' % code) self.emcc_args += ['--pre-js', 'postrun.js'] def add_on_exit(self, code): - create_file('onexit.js', 'Module.onExit = function() { %s }' % code) + assert not self.get_setting('MINIMAL_RUNTIME') + create_file('onexit.js', 'Module.onExit = function() { %s }\n' % code) self.emcc_args += ['--pre-js', 'onexit.js'] # returns the full list of arguments to pass to emcc diff --git a/test/core/test_main_reads_args.out b/test/core/test_main_reads_args.out index 51b7973e8c90b..051e3b5ed2fd3 100644 --- a/test/core/test_main_reads_args.out +++ b/test/core/test_main_reads_args.out @@ -1,2 +1,2 @@ argc: 1 -argv[0]: test_main_reads_args.js +argv\[0\]: (test_main_reads_args\.js|this\.program) diff --git a/test/minimal_runtime_exit_handling.js b/test/minimal_runtime_exit_handling.js index 0d9861e831811..4dc5c9a220533 100644 --- a/test/minimal_runtime_exit_handling.js +++ b/test/minimal_runtime_exit_handling.js @@ -1,19 +1,21 @@ -function onerror(e) { - // MINIMAL_RUNTIME + EXIT_RUNTIME throws `exit(status)` when exit() is called - // or when main is done. - // Unlike the normal runtime it doesn't call process.exit. - var message = e.message || e; - var offset = message.indexOf('exit('); - if (offset != -1) { - var status = message.substring(offset + 5); - offset = status.indexOf(')') - status = status.substr(0, offset) - process['exitCode'] = status; - } else { - console.log(e) - process['exitCode'] = 1; +if (typeof process != 'undefined') { + function onerror(e) { + // MINIMAL_RUNTIME + EXIT_RUNTIME throws `exit(status)` when exit() is called + // or when main is done. + // Unlike the normal runtime it doesn't call process.exit. + var message = e.message || e; + var offset = message.indexOf('exit('); + if (offset != -1) { + var status = message.substring(offset + 5); + offset = status.indexOf(')') + status = status.substr(0, offset) + process['exitCode'] = status; + } else { + console.log(e) + process['exitCode'] = 1; + } } -} -// Unhandled rejections end up here too because we run node with --unhandled-rejections=throw -process.on('uncaughtException', function(err, origin) { onerror(err); }); + // Unhandled rejections end up here too because we run node with --unhandled-rejections=throw + process.on('uncaughtException', function(err, origin) { onerror(err); }); +} diff --git a/test/test_core.py b/test/test_core.py index 8e34ba996d674..18e198233efcc 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -1780,6 +1780,8 @@ def test_ctors_no_main(self): @no_wasm2js('eval_ctors not supported yet') @also_with_standalone_wasm(impure=True) def test_eval_ctors_no_main(self): + if self.get_setting('MEMORY64') == 1: + self.skipTest('https://github.com/WebAssembly/binaryen/issues/5017') self.set_setting('EVAL_CTORS') self.emcc_args.append('--no-entry') self.do_core_test('test_ctors_no_main.cpp') @@ -2101,6 +2103,8 @@ def test_emscripten_get_compiler_setting(self): self.do_runf(src, read_file(output).replace('waka', shared.EMSCRIPTEN_VERSION)) def test_emscripten_has_asyncify(self): + if self.get_setting('MEMORY64') == 1: + self.skipTest('TODO: asyncify for wasm64') src = r''' #include #include @@ -5871,8 +5875,12 @@ def test_fs_mmap(self): self.uses_es6 = True for fs in ['MEMFS', 'NODEFS', 'NODERAWFS']: if fs == 'NODEFS': + if not self.have_node(): + continue self.emcc_args += ['-lnodefs.js'] if fs == 'NODERAWFS': + if not self.have_node(): + continue self.emcc_args += ['-lnodefs.js', '-lnoderawfs.js'] self.do_run_in_out_file_test('fs/test_mmap.c', emcc_args=['-D' + fs]) @@ -6095,6 +6103,9 @@ def test_unistd_io(self): self.emcc_args = orig_compiler_opts + ['-D' + fs] if fs == 'NODEFS': self.emcc_args += ['-lnodefs.js'] + if not self.have_node(): + # NODEFS requires node + continue if self.get_setting('WASMFS'): if fs == 'NODEFS': # TODO: NODEFS in WasmFS @@ -6222,6 +6233,7 @@ def test_iostream_and_determinism(self): def test_stdvec(self): self.do_core_test('test_stdvec.cpp') + @requires_node def test_random_device(self): self.maybe_closure() self.do_core_test('test_random_device.cpp') @@ -6493,7 +6505,11 @@ def test_mmap_anon_pthreads(self): self.do_core_test('test_mmap_anon.c') @no_lsan('Test code contains memory leaks') - def test_cubescript(self): + @parameterized({ + '': (False,), + '_asyncify': (True,) + }) + def test_cubescript(self, asyncify): # uses register keyword self.emcc_args += ['-std=c++03', '-Wno-dynamic-class-memaccess'] self.maybe_closure() @@ -6502,15 +6518,13 @@ def test_cubescript(self): if '-fsanitize=address' in self.emcc_args: self.emcc_args += ['--pre-js', test_file('asan-no-leak.js')] - def test(): - src = test_file('third_party/cubescript/command.cpp') - self.do_runf(src, '*\nTemp is 33\n9\n5\nhello, everyone\n*') + if asyncify: + if self.get_setting('MEMORY64'): + self.skipTest('TODO: asyncify for wasm64') + self.set_setting('ASYNCIFY') - test() - - print('asyncify') # extra coverage - self.set_setting('ASYNCIFY') - test() + src = test_file('third_party/cubescript/command.cpp') + self.do_runf(src, '*\nTemp is 33\n9\n5\nhello, everyone\n*') @needs_dylink def test_relocatable_void_function(self): @@ -6523,7 +6537,7 @@ def run(): self.do_runf(test_file('test_wasm_intrinsics_simd.c'), 'Success!') # Improves test readability self.emcc_args.append('-Wno-c++11-narrowing') - self.emcc_args.extend(['-Wpedantic', '-Werror', '-Wall', '-xc++']) + self.emcc_args = ['-Wpedantic', '-Werror', '-Wall', '-xc++'] + self.emcc_args run() self.emcc_args.append('-funsigned-char') run() @@ -6542,6 +6556,8 @@ def test_neon_wasm_simd(self): @no_safe_heap('has unaligned 64-bit operations in wasm') @no_ubsan('test contains UB') def test_sse1(self): + if self.is_wasm64(): + self.skipTest('https://github.com/llvm/llvm-project/issues/57577') src = test_file('sse/test_sse1.cpp') self.run_process([shared.CLANG_CXX, src, '-msse', '-o', 'test_sse1', '-D_CRT_SECURE_NO_WARNINGS=1'] + clang_native.get_clang_native_args(), stdout=PIPE) native_result = self.run_process('./test_sse1', stdout=PIPE).stdout @@ -6557,6 +6573,8 @@ def test_sse1(self): @no_safe_heap('has unaligned 64-bit operations in wasm') @is_slow_test def test_sse2(self): + if self.is_wasm64(): + self.skipTest('https://github.com/llvm/llvm-project/issues/57577') src = test_file('sse/test_sse2.cpp') self.run_process([shared.CLANG_CXX, src, '-msse2', '-Wno-argument-outside-range', '-o', 'test_sse2', '-D_CRT_SECURE_NO_WARNINGS=1'] + clang_native.get_clang_native_args(), stdout=PIPE) native_result = self.run_process('./test_sse2', stdout=PIPE).stdout @@ -6569,6 +6587,8 @@ def test_sse2(self): @wasm_simd @requires_native_clang def test_sse3(self): + if self.is_wasm64(): + self.skipTest('https://github.com/llvm/llvm-project/issues/57577') src = test_file('sse/test_sse3.cpp') self.run_process([shared.CLANG_CXX, src, '-msse3', '-Wno-argument-outside-range', '-o', 'test_sse3', '-D_CRT_SECURE_NO_WARNINGS=1'] + clang_native.get_clang_native_args(), stdout=PIPE) native_result = self.run_process('./test_sse3', stdout=PIPE).stdout @@ -6581,6 +6601,8 @@ def test_sse3(self): @wasm_simd @requires_native_clang def test_ssse3(self): + if self.is_wasm64(): + self.skipTest('https://github.com/llvm/llvm-project/issues/57577') src = test_file('sse/test_ssse3.cpp') self.run_process([shared.CLANG_CXX, src, '-mssse3', '-Wno-argument-outside-range', '-o', 'test_ssse3', '-D_CRT_SECURE_NO_WARNINGS=1'] + clang_native.get_clang_native_args(), stdout=PIPE) native_result = self.run_process('./test_ssse3', stdout=PIPE).stdout @@ -6594,6 +6616,8 @@ def test_ssse3(self): @requires_native_clang @is_slow_test def test_sse4_1(self): + if self.is_wasm64(): + self.skipTest('https://github.com/llvm/llvm-project/issues/57577') src = test_file('sse/test_sse4_1.cpp') if not self.is_optimizing() and '-fsanitize=address' in self.emcc_args: # ASan with -O0 fails with: @@ -6650,6 +6674,8 @@ def test_sse_diagnostics(self): @requires_native_clang @wasm_relaxed_simd def test_relaxed_simd_implies_simd128(self): + if self.is_wasm64(): + self.skipTest('https://github.com/llvm/llvm-project/issues/57577') src = test_file('sse/test_sse1.cpp') self.build(src, emcc_args=['-msse']) @@ -7662,6 +7688,7 @@ def test_webidl(self, mode, allow_memory_growth): '': ([],), 'minimal_runtime': (['-sMINIMAL_RUNTIME'],), }) + @requires_node def test_source_map(self, args): if '-g' not in self.emcc_args: self.emcc_args.append('-g') @@ -8125,6 +8152,7 @@ def test_fibers_asyncify(self): self.maybe_closure() self.do_runf(test_file('test_fibers.cpp'), '*leaf-0-100-1-101-1-102-2-103-3-104-5-105-8-106-13-107-21-108-34-109-*') + @no_wasm64('TODO: asyncify for wasm64') def test_asyncify_unused(self): # test a program not using asyncify, but the pref is set self.set_setting('ASYNCIFY') @@ -8577,6 +8605,7 @@ def test(assert_returncode=0): print('ENVIRONMENT =', self.get_setting('ENVIRONMENT')) test() + @requires_node def test_postrun_exception(self): # verify that an exception thrown in postRun() will not trigger the # compilation failed handler, and will be printed to stderr. @@ -9495,7 +9524,7 @@ def test_js_library_i64_params(self): def test_main_reads_args(self): self.run_process([EMCC, '-c', test_file('core/test_main_reads_args_real.c'), '-o', 'real.o'] + self.get_emcc_args(ldflags=False)) - self.do_core_test('test_main_reads_args.c', emcc_args=['real.o', '-sEXIT_RUNTIME']) + self.do_core_test('test_main_reads_args.c', emcc_args=['real.o', '-sEXIT_RUNTIME'], regex=True) # Generate tests for everything